open source
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
#ifdef JS_JSC
|
||||
#include "JSCArrayBuffer.h"
|
||||
#include <JavaScriptCore/JSTypedArray.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
#include "util/Log.h"
|
||||
#include <vector>
|
||||
#include "JSCProxyType.h"
|
||||
|
||||
namespace laya {
|
||||
|
||||
//TODO 这里没有考虑多线程的问题,如果js要支持多线程的话,需要修改。
|
||||
struct JsStrBuff {
|
||||
char* _buff;
|
||||
int _len;
|
||||
static std::vector<JsStrBuff> jsstrbuffs;
|
||||
static int curIdx;
|
||||
JsStrBuff() {
|
||||
_buff = NULL;
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
static JsStrBuff& getAData() {
|
||||
if (JsStrBuff::curIdx >= JsStrBuff::jsstrbuffs.size()) {
|
||||
JsStrBuff::jsstrbuffs.push_back(JsStrBuff());
|
||||
JsStrBuff::curIdx++;
|
||||
return JsStrBuff::jsstrbuffs.back();
|
||||
}
|
||||
else {
|
||||
return JsStrBuff::jsstrbuffs[JsStrBuff::curIdx++];
|
||||
}
|
||||
}
|
||||
};
|
||||
std::vector<JsStrBuff> JsStrBuff::jsstrbuffs;
|
||||
int JsStrBuff::curIdx = 0;
|
||||
|
||||
void resetJsStrBuf() {
|
||||
JsStrBuff::curIdx = 0;
|
||||
}
|
||||
|
||||
char* JsCharToC(JSStringRef str) {
|
||||
int len = 0;
|
||||
if (str == nullptr)
|
||||
return nullptr;//return "";
|
||||
len = JSStringGetMaximumUTF8CStringSize(str);
|
||||
if (len <= 0)
|
||||
return nullptr;//return "";
|
||||
JsStrBuff& curdata = JsStrBuff::getAData();
|
||||
char*& tocharBuf = curdata._buff;
|
||||
int& tocharBufLen = curdata._len;
|
||||
|
||||
//tocharBuf= new char[len + 1];
|
||||
if (len > tocharBufLen) {
|
||||
tocharBufLen = len;
|
||||
if (tocharBuf != NULL)
|
||||
delete[] tocharBuf;
|
||||
tocharBuf = new char[len+1];
|
||||
}
|
||||
else {
|
||||
//如果占用空间太大,也要重新分配
|
||||
if (tocharBufLen > 1024 ) {
|
||||
tocharBufLen = len;
|
||||
if (tocharBuf != NULL)
|
||||
delete[] tocharBuf;
|
||||
tocharBuf = new char[len+1];
|
||||
}
|
||||
}
|
||||
JSStringGetUTF8CString(str,tocharBuf,len);
|
||||
return tocharBuf;
|
||||
}
|
||||
char* JsCharToC(JSValueRef p_vl) {
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSStringRef str = JSValueToStringCopy(ctx, p_vl, nullptr);
|
||||
if (str == nullptr)
|
||||
return nullptr;//return "";
|
||||
char* ret = JsCharToC(str);
|
||||
JSStringRelease(str);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace laya{
|
||||
|
||||
static void deallocator(void* bytes, void* deallocatorContext)
|
||||
{
|
||||
if (bytes){
|
||||
delete (char*)bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSValueRef createJSAB(char* pData, int len)
|
||||
{
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
char* pBuffer = new char[len];
|
||||
memcpy(pBuffer, pData, len);
|
||||
return JSObjectMakeArrayBufferWithBytesNoCopy(ctx, pBuffer, len, deallocator, pBuffer, NULL);
|
||||
}
|
||||
JSValueRef createJSABAligned(char* pData, int len)
|
||||
{
|
||||
int asz = (len+3) & 0xfffffffc;
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
char* pBuffer = new char[asz];
|
||||
memcpy(pBuffer, pData, len);
|
||||
for( int i = len; i < asz; i++ )
|
||||
{
|
||||
pBuffer[i] = 0;
|
||||
}
|
||||
return JSObjectMakeArrayBufferWithBytesNoCopy(ctx, pBuffer, asz, deallocator, pBuffer, NULL);
|
||||
}
|
||||
bool extractJSAB(JSValueRef ab, char*& data, int& len)
|
||||
{
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSObjectRef arrayObj = JSValueToObject(ctx,ab,NULL);
|
||||
JSTypedArrayType arrayType = JSValueGetTypedArrayType(ctx, ab, NULL);
|
||||
switch(arrayType)
|
||||
{
|
||||
case kJSTypedArrayTypeNone:
|
||||
{
|
||||
data = NULL;
|
||||
len = 0;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case kJSTypedArrayTypeArrayBuffer:
|
||||
{
|
||||
data = (char*)JSObjectGetArrayBufferBytesPtr(ctx, arrayObj, NULL);
|
||||
len = (int)JSObjectGetArrayBufferByteLength(ctx, arrayObj, NULL);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
data = (char*)JSObjectGetTypedArrayBytesPtr(ctx, arrayObj, NULL) + JSObjectGetTypedArrayByteOffset(ctx, arrayObj, NULL);
|
||||
len = (int)JSObjectGetTypedArrayByteLength(ctx, arrayObj, NULL);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
#ifndef _JSC_ARRAYBUFFER_H_
|
||||
#define _JSC_ARRAYBUFFER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
|
||||
namespace laya{
|
||||
|
||||
JSValueRef createJSAB(char* pData, int len);
|
||||
JSValueRef createJSABAligned(char* pData, int len);
|
||||
bool extractJSAB(JSValueRef ab, char*& data, int& len);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifdef JS_JSC
|
||||
#include "JSCBinder.h"
|
||||
|
||||
pthread_key_t JSClassMgr::s_tls_curThread;
|
||||
|
||||
JSObjBaseJSC::JSObjBaseJSC() {
|
||||
m_bWeakThis = true;
|
||||
}
|
||||
|
||||
JSObjBaseJSC::~JSObjBaseJSC() {
|
||||
if (!m_bWeakThis){
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSValueUnprotect(ctx, mpJsThis);
|
||||
}
|
||||
}
|
||||
|
||||
void JSObjBaseJSC::retainThis() {
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSValueProtect(ctx, mpJsThis);
|
||||
}
|
||||
|
||||
void JSObjBaseJSC::releaseThis() {
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSValueUnprotect(ctx, mpJsThis);
|
||||
}
|
||||
|
||||
|
||||
void JSObjBaseJSC::createJSObj(){
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
mpJsThis = JSObjectMake(ctx,nullptr,nullptr);
|
||||
JSValueProtect(ctx, mpJsThis);
|
||||
m_bWeakThis = false;
|
||||
}
|
||||
|
||||
JSValueRef JSObjBaseJSC::callJsFunc(JSValueRef func) {
|
||||
return _callJsFunc(func, 0, nullptr);
|
||||
}
|
||||
|
||||
bool JsObjHandleJSC::Empty() {
|
||||
if (!m_pObj)
|
||||
return true;
|
||||
return m_pValue == nullptr;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,373 @@
|
||||
#ifndef _JSC_BINDER_H__
|
||||
#define _JSC_BINDER_H__
|
||||
#include <JavaScriptCore/JSObjectRef.h>
|
||||
#include "JSCProxyTransfer.h"
|
||||
#include "JSCProxyType.h"
|
||||
#include "JSCProxyClass.h"
|
||||
#include <pthread.h>
|
||||
using namespace laya;
|
||||
|
||||
class JSClassMgr{
|
||||
public:
|
||||
static pthread_key_t s_tls_curThread;
|
||||
typedef void (*RESETFUNC)();
|
||||
static JSClassMgr* GetThreadInstance(){
|
||||
JSClassMgr* pIns =(JSClassMgr*)pthread_getspecific(s_tls_curThread);
|
||||
if(!pIns){
|
||||
pIns = new JSClassMgr();
|
||||
pthread_setspecific(s_tls_curThread,(void*)pIns);
|
||||
}
|
||||
return pIns;
|
||||
}
|
||||
std::vector<RESETFUNC> allCls;
|
||||
void resetAllRegClass(){
|
||||
for( int i=0,sz=allCls.size(); i<sz; i++){
|
||||
allCls[i]();
|
||||
}
|
||||
allCls.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#define JSP_GLOBAL_START1()
|
||||
|
||||
#define JSP_ADD_GLOBAL_FUNCTION(name, func, ...) \
|
||||
JSCGlobal::getInstance()->addFunction( #name, func );
|
||||
|
||||
#define JSP_ADD_GLOBAL_PROPERTY(name, v) \
|
||||
JSCGlobal::getInstance()->addProperty( #name, v );
|
||||
|
||||
|
||||
|
||||
|
||||
#define JSP_CLASS(name, cls) \
|
||||
JSCClass<cls>* pJSCClass = JSCClass<cls>::getInstance();
|
||||
|
||||
#define JSP_GLOBAL_CLASS(name, cls) \
|
||||
JSCClass<cls>* pJSCClass = JSCClass<cls>::getInstance();
|
||||
|
||||
#define JSP_ADD_FIXED_PROPERTY(name,cls,val) \
|
||||
pJSCClass->addFixedProperty(#name,val)
|
||||
|
||||
#define JSP_ADD_METHOD(name,fn) \
|
||||
pJSCClass->addMethod(name,&fn);
|
||||
|
||||
#define JSP_ADD_PROPERTY_RO(name,cls,getter) \
|
||||
pJSCClass->addProperty(#name,&cls::getter,nullptr);
|
||||
|
||||
#define JSP_ADD_PROPERTY(name,cls,getter,setter) \
|
||||
pJSCClass->addProperty(#name,&cls::getter,&cls::setter);
|
||||
|
||||
#define JSP_REG_CONSTRUCTOR(cls,...) \
|
||||
pJSCClass->addConstructor(laya::regConstructor<cls,##__VA_ARGS__>());
|
||||
|
||||
|
||||
#define JSP_INSTALL_CLASS(name,cls) \
|
||||
pJSCClass->finish(name); \
|
||||
JSClassMgr::GetThreadInstance()->allCls.push_back(JSCClass<cls>::reset);
|
||||
|
||||
#define JSP_INSTALL_GLOBAL_CLASS(name,cls,inst) \
|
||||
pJSCClass->finishToGlobal(name,inst); \
|
||||
JSClassMgr::GetThreadInstance()->allCls.push_back(JSCClass<cls>::reset);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class JSObjBaseJSC {
|
||||
friend class JsObjHandleJSC;
|
||||
public:
|
||||
JSObjBaseJSC();
|
||||
virtual ~JSObjBaseJSC();
|
||||
|
||||
void retainThis();
|
||||
void releaseThis();
|
||||
void createJSObj();
|
||||
|
||||
bool IsMyJsEnv() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline JSValueRef _callJsFunc(JSValueRef func, size_t argumentCount, const JSValueRef arguments[]) {
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSValueRef exception = nullptr;
|
||||
JSObjectRef funcObj = JSValueToObject(ctx,func,&exception);
|
||||
if (exception != nullptr){
|
||||
__JSRun::OutputException(exception);
|
||||
}
|
||||
JSValueRef ret = JSObjectCallAsFunction(ctx,funcObj,mpJsThis,argumentCount,arguments,&exception);
|
||||
if (exception != nullptr){
|
||||
__JSRun::OutputException(exception);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
JSValueRef callJsFunc(JSValueRef func);
|
||||
|
||||
template<class P1>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1) {
|
||||
int argc = 1;
|
||||
JSValueRef argv[1];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
|
||||
template<class P1, class P2>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2) {
|
||||
int argc = 2;
|
||||
JSValueRef argv[2];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3) {
|
||||
int argc = 3;
|
||||
JSValueRef argv[3];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4) {
|
||||
int argc = 4;
|
||||
JSValueRef argv[4];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4, class P5>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
|
||||
int argc = 5;
|
||||
JSValueRef argv[5];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
argv[4] = __TransferToJs<P5>::ToJs(p5);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4, class P5, class P6>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
|
||||
int argc = 6;
|
||||
JSValueRef argv[6];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
argv[4] = __TransferToJs<P5>::ToJs(p5);
|
||||
argv[5] = __TransferToJs<P6>::ToJs(p6);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
|
||||
int argc = 7;
|
||||
JSValueRef argv[7];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
argv[4] = __TransferToJs<P5>::ToJs(p5);
|
||||
argv[5] = __TransferToJs<P6>::ToJs(p6);
|
||||
argv[6] = __TransferToJs<P7>::ToJs(p7);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
|
||||
int argc = 8;
|
||||
JSValueRef argv[8];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
argv[4] = __TransferToJs<P5>::ToJs(p5);
|
||||
argv[5] = __TransferToJs<P6>::ToJs(p6);
|
||||
argv[6] = __TransferToJs<P7>::ToJs(p7);
|
||||
argv[7] = __TransferToJs<P8>::ToJs(p8);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
|
||||
JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {
|
||||
int argc = 12;
|
||||
JSValueRef argv[12];
|
||||
argv[0] = __TransferToJs<P1>::ToJs(p1);
|
||||
argv[1] = __TransferToJs<P2>::ToJs(p2);
|
||||
argv[2] = __TransferToJs<P3>::ToJs(p3);
|
||||
argv[3] = __TransferToJs<P4>::ToJs(p4);
|
||||
argv[4] = __TransferToJs<P5>::ToJs(p5);
|
||||
argv[5] = __TransferToJs<P6>::ToJs(p6);
|
||||
argv[6] = __TransferToJs<P7>::ToJs(p7);
|
||||
argv[7] = __TransferToJs<P8>::ToJs(p8);
|
||||
argv[8] = __TransferToJs<P8>::ToJs(p9);
|
||||
argv[9] = __TransferToJs<P8>::ToJs(p10);
|
||||
argv[10] = __TransferToJs<P8>::ToJs(p11);
|
||||
argv[11] = __TransferToJs<P8>::ToJs(p12);
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
public:
|
||||
JSObjectRef mpJsThis;
|
||||
bool m_bWeakThis;
|
||||
};
|
||||
|
||||
class JsObjHandleJSC
|
||||
{
|
||||
public:
|
||||
JsObjHandleJSC() {
|
||||
m_pObj = nullptr;
|
||||
m_pValue = nullptr;
|
||||
m_pReturn = nullptr;
|
||||
}
|
||||
~JsObjHandleJSC(){
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
if (m_pValue != nullptr && ctx != nullptr)
|
||||
{
|
||||
JSValueUnprotect(ctx, m_pValue);
|
||||
}
|
||||
}
|
||||
JSObjBaseJSC* m_pObj;
|
||||
JSValueRef m_pValue;
|
||||
JSValueRef m_pReturn;
|
||||
bool Empty();
|
||||
|
||||
JSValueRef getJsObj() {
|
||||
return m_pValue;
|
||||
}
|
||||
|
||||
void set(int id, JSObjBaseJSC* pobj, JSValueRef v) {
|
||||
if (m_pValue != nullptr){
|
||||
Reset();
|
||||
}
|
||||
m_pValue = v;
|
||||
JSValueProtect(__TlsData::GetInstance()->GetCurContext(), m_pValue);
|
||||
m_pObj = pobj;
|
||||
|
||||
}
|
||||
template <typename _Tp>
|
||||
static bool IsTypeof(JSValueRef val) {
|
||||
if (val == nullptr)
|
||||
return false;
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
__InferType<_Tp> _it;
|
||||
switch (_it.iType) {
|
||||
case __VT_void:
|
||||
return false;
|
||||
case __VT_string:
|
||||
return JSValueIsString(ctx, val);
|
||||
case __VT_bool:
|
||||
return JSValueIsBoolean(ctx, val);
|
||||
case __VT_int:
|
||||
case __VT_long:
|
||||
case __VT_float:
|
||||
case __VT_double:
|
||||
case __VT_longlong:
|
||||
return JSValueIsNumber(ctx,val);
|
||||
default: {
|
||||
return __CheckClassType::IsTypeOf<_Tp>(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
bool IsTypeof() {
|
||||
return IsTypeof<_Tp>(m_pValue);
|
||||
}
|
||||
|
||||
template <typename _R>
|
||||
static bool tryGet(JSValueRef val, _R **pRet) {
|
||||
if (val == nullptr) {
|
||||
*pRet = 0;
|
||||
return false;
|
||||
}
|
||||
if (!__TransferToCpp<_R>::is(val))
|
||||
return false;
|
||||
*pRet = __TransferToCpp<_R*>::ToCpp(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tryGetStr(JSValueRef val, char** ppRet) {
|
||||
if (JSValueIsString(__TlsData::GetInstance()->GetCurContext(), val)) {
|
||||
*ppRet = JsCharToC(val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
if (m_pValue != nullptr && ctx != nullptr){
|
||||
JSValueUnprotect(ctx, m_pValue);
|
||||
m_pValue = nullptr;
|
||||
}
|
||||
}
|
||||
void __BindThis(JsObjHandleJSC &p_This) {}
|
||||
bool IsFunction() {
|
||||
if (!m_pObj)return false;
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSObjectRef valueObj = JSValueToObject(ctx, m_pValue, nullptr);
|
||||
if (!JSObjectIsFunction(ctx, valueObj))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return m_pValue != nullptr && m_pObj != nullptr && m_pObj->IsMyJsEnv();
|
||||
}
|
||||
|
||||
#define CALLJSPRE \
|
||||
if (!m_pObj)return false; \
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext(); \
|
||||
JSObjectRef func = JSValueToObject(ctx, m_pValue, nullptr); \
|
||||
if (!JSObjectIsFunction(ctx,func)) \
|
||||
return false;
|
||||
|
||||
bool Call() {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func);
|
||||
return true;
|
||||
}
|
||||
template <typename P1>
|
||||
bool Call(P1 p1) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func,p1);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2>
|
||||
bool Call(P1 p1, P2 p2) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2, typename P3>
|
||||
bool Call(P1 p1, P2 p2, P3 p3) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2, typename P3, typename P4>
|
||||
bool Call(P1 p1, P2 p2, P3 p3, P4 p4) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3, p4);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3, p4, p5);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3, p4, p5, p6);
|
||||
return true;
|
||||
}
|
||||
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
|
||||
CALLJSPRE
|
||||
m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3, p4, p5, p6, p7);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
@file JSCEnv.cpp
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2018_8_23
|
||||
*/
|
||||
|
||||
#include "JSCEnv.h"
|
||||
#include "../../../CToObjectC.h"
|
||||
#ifdef __APPLE__
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
namespace laya
|
||||
{
|
||||
pthread_key_t __TlsData::s_tls_curThread;
|
||||
static JSValueRef gcCallback( JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception )
|
||||
{
|
||||
JSGlobalContextRef pCtx = JSContextGetGlobalContext(ctx);
|
||||
JSGarbageCollect( pCtx );
|
||||
//JSSynchronousEdenCollectForDebugging(pCtx);
|
||||
//JSSynchronousGarbageCollectForDebugging(pCtx);
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
void AlertOnJsException(bool b)
|
||||
{
|
||||
|
||||
}
|
||||
void Javascript::initJSEngine()
|
||||
{
|
||||
m_pGlobalContext = JSGlobalContextCreateInGroup(NULL, NULL);
|
||||
m_pUndefined = JSValueMakeUndefined(m_pGlobalContext);
|
||||
JSValueProtect(m_pGlobalContext, m_pUndefined);
|
||||
__TlsData::GetInstance()->SetCurContext(m_pGlobalContext);
|
||||
|
||||
// expose gc()
|
||||
JSStringRef pJSName = JSStringCreateWithUTF8CString("gc");
|
||||
JSObjectRef pFunc = JSObjectMakeFunctionWithCallback(m_pGlobalContext, pJSName, gcCallback);
|
||||
JSValueRef exception = 0;
|
||||
JSObjectSetProperty(m_pGlobalContext, JSContextGetGlobalObject(m_pGlobalContext), pJSName, pFunc, kJSPropertyAttributeDontDelete, &exception);
|
||||
if (0 != exception)
|
||||
{
|
||||
__JSRun::OutputException(exception);
|
||||
}
|
||||
JSStringRelease(pJSName);
|
||||
|
||||
}
|
||||
void Javascript::uninitJSEngine()
|
||||
{
|
||||
__TlsData::GetInstance()->SetCurContext(NULL);
|
||||
JSValueUnprotect(m_pGlobalContext, m_pUndefined);
|
||||
JSGlobalContextRelease(m_pGlobalContext);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
JSCWorker::JSCWorker()
|
||||
{
|
||||
|
||||
}
|
||||
JSCWorker::~JSCWorker()
|
||||
{
|
||||
|
||||
}
|
||||
void JSCWorker::stop()
|
||||
{
|
||||
if (m_bStop)return;
|
||||
m_bStop = true;
|
||||
m_ThreadTasks.Stop();
|
||||
m_bdbgThreadStarted = false;
|
||||
}
|
||||
void JSCWorker::_defRunLoop()
|
||||
{
|
||||
//设置tls
|
||||
pthread_setspecific(s_tls_curThread, (void*)this);
|
||||
|
||||
//开始事件
|
||||
JCEventEmitter::evtPtr startEvt(new JCEventBase);
|
||||
startEvt->m_nID = JCWorkerThread::Event_threadStart;
|
||||
emit(startEvt);
|
||||
|
||||
CToObjectCRunJSLoop();
|
||||
|
||||
//退出事件
|
||||
JCEventEmitter::evtPtr stopEvt(new JCEventBase);
|
||||
stopEvt->m_nID = JCWorkerThread::Event_threadStop;
|
||||
emit(stopEvt);
|
||||
}
|
||||
void JSCWorker::_runLoop()
|
||||
{
|
||||
m_pJS->initJSEngine();
|
||||
_defRunLoop();
|
||||
m_pJS->uninitJSEngine();
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
@file JSCEnv.h
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2018_8_23
|
||||
*/
|
||||
|
||||
#ifndef __JSCEnv_H__
|
||||
#define __JSCEnv_H__
|
||||
|
||||
#include <JavaScriptCore/JavaScriptCore.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
#include <misc/JCWorkerThread.h>
|
||||
|
||||
namespace laya
|
||||
{
|
||||
void JSPrint( const char* p_sBuffer );
|
||||
void JSAlert( const char* p_sBuffer );
|
||||
void JSAlertExit( const char* p_sBuffer );
|
||||
void evalJS( const char* p_sSource );
|
||||
|
||||
class Javascript
|
||||
{
|
||||
public:
|
||||
|
||||
typedef void(*voidfun)(void* data);
|
||||
Javascript()
|
||||
{
|
||||
|
||||
}
|
||||
void init(int nPort)
|
||||
{
|
||||
|
||||
}
|
||||
void run(const char* sSource)
|
||||
{
|
||||
|
||||
}
|
||||
void run(const char* sSource, std::function<void(void)> preRunFunc)
|
||||
{
|
||||
|
||||
}
|
||||
void run(voidfun func, void* pdata)
|
||||
{
|
||||
|
||||
}
|
||||
void uninit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void initJSEngine();
|
||||
|
||||
void uninitJSEngine();
|
||||
|
||||
public:
|
||||
|
||||
JSGlobalContextRef m_pGlobalContext;
|
||||
JSValueRef m_pUndefined;
|
||||
};
|
||||
|
||||
class JSThreadInterface
|
||||
{
|
||||
public:
|
||||
JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual void post(std::function<void(void)> func) = 0;
|
||||
virtual void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void initialize(int nPort) = 0;
|
||||
virtual void uninitialize() = 0;
|
||||
virtual void setLoopFunc(std::function<bool(void)> func) = 0;
|
||||
virtual void pushDbgFunc(std::function<void(void)> task) = 0;
|
||||
virtual void runDbgFuncs() = 0;
|
||||
virtual void waitAndRunDbgFuncs() = 0;
|
||||
virtual bool hasDbgFuncs() = 0;
|
||||
virtual JCWorkerThread* getWorker() = 0;
|
||||
virtual void run(Javascript::voidfun func, void* pData) = 0;
|
||||
virtual void clearFunc() = 0;
|
||||
};
|
||||
|
||||
class JSCWorker : public JCWorkerThread
|
||||
{
|
||||
public:
|
||||
|
||||
JSCWorker();
|
||||
|
||||
~JSCWorker();
|
||||
|
||||
virtual void _defRunLoop();
|
||||
|
||||
virtual void _runLoop();
|
||||
|
||||
virtual void stop();
|
||||
|
||||
public:
|
||||
|
||||
Javascript* m_pJS;
|
||||
|
||||
};
|
||||
|
||||
class JSMulThread : public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
JSMulThread()
|
||||
{
|
||||
m_kWorker.setThreadName("JavaScript Main");
|
||||
m_kWorker.m_pJS = &m_kJS;
|
||||
}
|
||||
~JSMulThread()
|
||||
{
|
||||
|
||||
}
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
if (m_kWorker.m_bStop)return;
|
||||
CToObjectCPostFunc(func);
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0)
|
||||
{
|
||||
m_kWorker.on(nEvent, func, (JCWorkerThread*)pInThread);
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kWorker.start();
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kWorker.stop();
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
m_kJS.init(nPort);
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
m_kJS.uninit();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
m_kWorker.setLoopFunc(func);
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return &m_kWorker;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
m_kWorker.runQueue();
|
||||
m_kWorker.m_funcLoop();
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
}
|
||||
public:
|
||||
|
||||
Javascript m_kJS;
|
||||
JSCWorker m_kWorker;
|
||||
};
|
||||
|
||||
class JSSingleThread : public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
JSSingleThread()
|
||||
{
|
||||
}
|
||||
~JSSingleThread()
|
||||
{
|
||||
|
||||
}
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
//if (m_kWorker.m_bStop)return;
|
||||
//CToObjectCPostFunc(func);
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.push_back(func);
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0)
|
||||
{
|
||||
switch (nEvent)
|
||||
{
|
||||
case JCWorkerThread::Event_threadStart:
|
||||
m_kStartFunc.func = func;
|
||||
m_kStartFunc.bDel = false;
|
||||
break;
|
||||
case JCWorkerThread::Event_threadStop:
|
||||
m_kStopFunc.func = func;
|
||||
m_kStopFunc.bDel = false;
|
||||
break;
|
||||
default:
|
||||
LOGE("JSSingleThread on() event type error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kStartFunc.func(NULL);
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kStopFunc.func(NULL);
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.init(nPort);
|
||||
m_kJS.initJSEngine();
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.uninitJSEngine();
|
||||
m_kJS.uninit();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
m_kLoopFunc = func;
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
runFunQueue();
|
||||
m_kLoopFunc();
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.clear();
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
public:
|
||||
|
||||
void runFunQueue()
|
||||
{
|
||||
std::vector<std::function<void(void)>> vWorkQueue;
|
||||
m_kQueueLock.lock();
|
||||
std::swap(vWorkQueue, m_vFuncQueue);
|
||||
m_kQueueLock.unlock();
|
||||
for (int i = 0; i < (int)vWorkQueue.size(); i++)
|
||||
{
|
||||
vWorkQueue[i]();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Javascript m_kJS;
|
||||
JCEventEmitter::EvtHandlerPack m_kStartFunc;
|
||||
JCEventEmitter::EvtHandlerPack m_kStopFunc;
|
||||
std::vector<std::function<void(void)>> m_vFuncQueue;
|
||||
std::mutex m_kQueueLock;
|
||||
std::function<bool(void)> m_kLoopFunc;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JSCEnv_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// JSCPropertyHandle.h
|
||||
// conch
|
||||
//
|
||||
// Created by joychina on 15/6/27.
|
||||
// Copyright (c) 2015年 LayaBox. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef conch_JSCPropertyHandle_h
|
||||
#define conch_JSCPropertyHandle_h
|
||||
|
||||
#include <JavaScriptCore/JavaScriptCore.h>
|
||||
#include <JavaScriptCore/JavaScript.h>
|
||||
#include <JavaScriptCore/JSObjectRef.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
namespace laya
|
||||
{
|
||||
class JSCProxyArray
|
||||
{
|
||||
public:
|
||||
JSValueRef pJSArray;
|
||||
JSContextRef pContext;
|
||||
JSValueRef pTmp;
|
||||
|
||||
public:
|
||||
void initArrayByScript(const char* szScript)
|
||||
{
|
||||
__JSRun::Run(szScript,&pJSArray);
|
||||
pContext = __TlsData::GetInstance()->GetCurContext();
|
||||
}
|
||||
|
||||
int getLength()
|
||||
{
|
||||
JSStringRef pname = JSStringCreateWithUTF8CString("length");
|
||||
JSValueRef exception = 0;
|
||||
JSValueRef val = JSObjectGetProperty(pContext, (JSObjectRef)pJSArray, pname, &exception);
|
||||
|
||||
if( 0 != exception )
|
||||
{
|
||||
__JSRun::OutputException( exception );
|
||||
}
|
||||
|
||||
double _len =JSValueToNumber(pContext, val, &exception);
|
||||
if( 0 != exception )
|
||||
{
|
||||
__JSRun::OutputException( exception );
|
||||
}
|
||||
JSStringRelease(pname);
|
||||
return (int)_len;
|
||||
}
|
||||
|
||||
JSValueRef &operator [](int nIndex)
|
||||
{
|
||||
JSValueRef exception = 0;
|
||||
pTmp = JSObjectGetPropertyAtIndex(pContext, (JSObjectRef)pJSArray, nIndex, &exception);
|
||||
if( 0 != exception )
|
||||
{
|
||||
__JSRun::OutputException( exception );
|
||||
}
|
||||
return pTmp;
|
||||
}
|
||||
|
||||
void setPropertyValue(unsigned int index,JSValueRef value){
|
||||
JSValueRef exception = 0;
|
||||
JSObjectSetPropertyAtIndex(pContext, (JSObjectRef)pJSArray, index, value, &exception);
|
||||
if( 0 != exception )
|
||||
{
|
||||
__JSRun::OutputException( exception );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,615 @@
|
||||
|
||||
#ifndef _JSCProxyClass_h
|
||||
#define _JSCProxyClass_h
|
||||
|
||||
#include <unordered_map>
|
||||
#include "JSCProxyTransfer.h"
|
||||
#include "JSCProxyFunction.h"
|
||||
#include "JSCProxyType.h"
|
||||
|
||||
|
||||
namespace laya
|
||||
{
|
||||
|
||||
class JSCGlobal
|
||||
{
|
||||
public:
|
||||
JSCGlobal(){}
|
||||
~JSCGlobal(){
|
||||
reset();
|
||||
}
|
||||
template <typename T>
|
||||
void addProperty( const std::string& name, T value ){
|
||||
assert( !name.empty());
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSStringRef pJSStrName = JSStringCreateWithUTF8CString( name.c_str() );
|
||||
JSValueRef pVal = __TransferToJs<T>::ToJs( value );
|
||||
JSObjectSetProperty( pCtx, JSContextGetGlobalObject( pCtx ), pJSStrName, pVal, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly, nullptr );
|
||||
JSStringRelease( pJSStrName );
|
||||
}
|
||||
template <typename T>
|
||||
void addFunction( const std::string& name, T fun ){
|
||||
assert( !name.empty() );
|
||||
IJSCFunction* pJSCFunction = new JSCFunction<T>( fun );
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSStringRef pjsName = JSStringCreateWithUTF8CString( name.c_str() );
|
||||
JSObjectRef pFunc = JSObjectMakeFunctionWithCallback(pCtx, pjsName, JSObjectCallAsFunctionCallback);
|
||||
JSObjectSetProperty(pCtx, JSContextGetGlobalObject(pCtx), pjsName, pFunc, kJSPropertyAttributeDontDelete|kJSPropertyAttributeReadOnly, nullptr);
|
||||
JSStringRelease( pjsName );
|
||||
FunctionMapRes rs = m_FunctionMap.insert(FunctionMapValue((unsigned long)pFunc, pJSCFunction));
|
||||
assert( rs.second );
|
||||
}
|
||||
IJSCFunction* getFunction(unsigned long func){
|
||||
FunctionMapItr itrFun = m_FunctionMap.find( func );
|
||||
if ( itrFun != m_FunctionMap.end() ){
|
||||
return itrFun->second;
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
static JSValueRef JSObjectCallAsFunctionCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
IJSCFunction* pJSCFunction = JSCGlobal::getInstance()->getFunction( (unsigned long)function );
|
||||
if ( pJSCFunction == nullptr ){
|
||||
__JsThrow::Throw(exception,"JSCGlobal::JSObjectCallAsFunctionCallback can't find function");
|
||||
return nullptr;
|
||||
}
|
||||
return pJSCFunction->call(ctx, function, thisObject, argumentCount, arguments, exception);
|
||||
}
|
||||
static JSCGlobal* getInstance(){
|
||||
static JSCGlobal instance;
|
||||
return &instance;
|
||||
}
|
||||
void reset(){
|
||||
FunctionMapItr iter = m_FunctionMap.begin();
|
||||
for (; iter != m_FunctionMap.end(); iter++){
|
||||
delete iter->second;
|
||||
}
|
||||
m_FunctionMap.clear();
|
||||
}
|
||||
private:
|
||||
typedef std::unordered_map<unsigned long,IJSCFunction*> FunctionMap;
|
||||
typedef FunctionMap::value_type FunctionMapValue;
|
||||
typedef FunctionMap::iterator FunctionMapItr;
|
||||
typedef std::pair<FunctionMapItr,bool> FunctionMapRes;
|
||||
FunctionMap m_FunctionMap;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class JSCClass
|
||||
{
|
||||
public:
|
||||
inline unsigned int __hash_BKDR(const char *p_str){
|
||||
if( 0 == p_str )
|
||||
return 0;
|
||||
|
||||
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
|
||||
unsigned int hash = 0;
|
||||
|
||||
for(;0!=*p_str;){
|
||||
hash = hash * seed + (*p_str++);
|
||||
}
|
||||
|
||||
return (hash & 0x7FFFFFFF);
|
||||
}
|
||||
class FuncEntry
|
||||
{
|
||||
enum
|
||||
{
|
||||
Max_Arg_Size = 12,
|
||||
Invalid_size = -1,
|
||||
};
|
||||
IJSCCallback *m_funcs[Max_Arg_Size+1];
|
||||
int m_iMaxArgSize;
|
||||
|
||||
public:
|
||||
FuncEntry(){
|
||||
m_iMaxArgSize = Invalid_size;
|
||||
memset( m_funcs, 0, sizeof(m_funcs) );
|
||||
}
|
||||
|
||||
~FuncEntry(){
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(){
|
||||
for(int i=0;i<=Max_Arg_Size;++i){
|
||||
if( 0 != m_funcs[i] ){
|
||||
delete m_funcs[i];
|
||||
m_funcs[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add( IJSCCallback *p_fn ){
|
||||
assert(p_fn != nullptr && p_fn->getNumArgs() <= Max_Arg_Size && m_funcs[p_fn->getNumArgs()] == nullptr );
|
||||
if( m_iMaxArgSize < p_fn->getNumArgs() )
|
||||
m_iMaxArgSize = p_fn->getNumArgs();
|
||||
m_funcs[p_fn->getNumArgs()] = p_fn;
|
||||
}
|
||||
|
||||
IJSCCallback *get( int p_iArgNum ){
|
||||
if( Invalid_size == m_iMaxArgSize ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( p_iArgNum > m_iMaxArgSize )
|
||||
p_iArgNum = m_iMaxArgSize;
|
||||
|
||||
for(;p_iArgNum>=0;p_iArgNum--){
|
||||
if( 0 != m_funcs[p_iArgNum] )
|
||||
return m_funcs[p_iArgNum];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
enum
|
||||
{
|
||||
CallbackType_Property,
|
||||
CallbackType_Function,
|
||||
};
|
||||
struct CallbackDefine
|
||||
{
|
||||
int m_iType;
|
||||
std::string m_name;
|
||||
IJSCCallback* m_pSetter;
|
||||
IJSCCallback* m_pGetter;
|
||||
|
||||
FuncEntry m_Method;
|
||||
JSValueRef m_pCallAsFunction;
|
||||
|
||||
CallbackDefine(const std::string& name, IJSCCallback* setter, IJSCCallback* getter)
|
||||
:m_name(name), m_iType(CallbackType_Property), m_pSetter(setter), m_pGetter(getter),m_pCallAsFunction(nullptr){
|
||||
}
|
||||
|
||||
CallbackDefine(const std::string& name,IJSCCallback* method)
|
||||
:m_name(name), m_iType(CallbackType_Function), m_pSetter(nullptr), m_pGetter(nullptr),m_pCallAsFunction(nullptr){
|
||||
m_Method.add(method);
|
||||
}
|
||||
|
||||
void addMethod( IJSCCallback *p_pfn ){
|
||||
m_Method.add(p_pfn);
|
||||
}
|
||||
|
||||
IJSCCallback *getMethod( size_t p_iArgNum ){
|
||||
return m_Method.get( (int)p_iArgNum );
|
||||
}
|
||||
~CallbackDefine(){
|
||||
|
||||
if (m_pGetter){
|
||||
delete m_pGetter;
|
||||
m_pGetter = nullptr;
|
||||
}
|
||||
|
||||
if (m_pSetter){
|
||||
delete m_pSetter;
|
||||
m_pSetter = nullptr;
|
||||
}
|
||||
|
||||
m_Method.reset();
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
if (ctx != nullptr && m_pCallAsFunction != nullptr){
|
||||
JSValueUnprotect(ctx, m_pCallAsFunction);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
struct FixedProperty
|
||||
{
|
||||
private:
|
||||
JSValueRef m_pszName;
|
||||
JSValueRef m_pValue;
|
||||
|
||||
public:
|
||||
template <typename _Tp>
|
||||
explicit FixedProperty( const char *p_pszName, _Tp p_Val )
|
||||
{
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
|
||||
JSStringRef pszName = JSStringCreateWithUTF8CString(p_pszName);
|
||||
m_pszName = JSValueMakeString(pCtx, pszName);
|
||||
JSStringRelease(pszName);
|
||||
|
||||
m_pValue = __TransferToJs<_Tp>::ToJs(p_Val);
|
||||
|
||||
JSValueProtect( pCtx, m_pszName );
|
||||
JSValueProtect( pCtx, m_pValue );
|
||||
}
|
||||
|
||||
~FixedProperty()
|
||||
{
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
if( 0 != pCtx )
|
||||
{
|
||||
if( 0 != m_pszName )
|
||||
{
|
||||
JSValueUnprotect( pCtx, m_pszName );
|
||||
}
|
||||
if( 0 != m_pValue )
|
||||
{
|
||||
JSValueUnprotect( pCtx, m_pValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSStringRef GetName()
|
||||
{
|
||||
return JSValueToStringCopy(__TlsData::GetInstance()->GetCurContext(), m_pszName, 0);
|
||||
}
|
||||
|
||||
JSValueRef GetValue()
|
||||
{
|
||||
return m_pValue;
|
||||
}
|
||||
};
|
||||
typedef std::vector<FixedProperty *> FixedProperties;
|
||||
typedef typename FixedProperties::iterator FixedPropertiesIter;
|
||||
|
||||
FixedProperties m_FixedProperties;
|
||||
|
||||
JSCClass(){
|
||||
m_bIsGlobal = false;
|
||||
m_ClassDefine = kJSClassDefinitionEmpty;
|
||||
m_ClassObject = nullptr;
|
||||
m_iTypeID = __hash_BKDR(typeid(T).name());
|
||||
}
|
||||
~JSCClass(){
|
||||
_reset();
|
||||
}
|
||||
unsigned int getTypeID(){
|
||||
return m_iTypeID;
|
||||
}
|
||||
static JSCClass* getInstance(){
|
||||
static JSCClass<T> instance;
|
||||
return &instance;
|
||||
}
|
||||
template <typename P>
|
||||
void addFixedProperty(const std::string& name,const P& val){
|
||||
assert(!name.empty());
|
||||
m_FixedProperties.push_back(new FixedProperty(name.c_str(),val));
|
||||
}
|
||||
template <typename G,typename S>
|
||||
void addProperty( const std::string& name, G getter, S setter){
|
||||
assert( !name.empty() );
|
||||
IJSCCallback* pGetter = new JSCCallback<G>(getter);
|
||||
IJSCCallback* pSetter = nullptr;
|
||||
if (setter != nullptr){
|
||||
pSetter = new JSCCallback<S>(setter);
|
||||
}
|
||||
PropertyMapRes rs = m_PropertyMap.insert(PropertyMapValue(name,new CallbackDefine(name,pSetter,pGetter)));
|
||||
assert(rs.second && "JSCClass::addProperty name is dumplicate value");
|
||||
}
|
||||
void addConstructor( IJSCCallback* constructor ){
|
||||
m_Constructor.add(constructor);
|
||||
}
|
||||
template<typename M>
|
||||
void addMethod( const std::string& name, M method ){
|
||||
|
||||
PropertyMapItr iter = m_PropertyMap.find(name);
|
||||
|
||||
if ( iter != m_PropertyMap.end() ){
|
||||
assert( iter->second->m_iType == CallbackType_Function );
|
||||
iter->second->addMethod(new JSCCallback<M>(method));
|
||||
return;
|
||||
}
|
||||
CallbackDefine* pProperty = new CallbackDefine(name,new JSCCallback<M>(method));
|
||||
JSStringRef pName = JSStringCreateWithUTF8CString(name.c_str());
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
pProperty->m_pCallAsFunction = JSObjectMakeFunctionWithCallback(pCtx, pName, JSCClass<T>::callAsFunctionCallback);
|
||||
JSStringRelease(pName);
|
||||
JSValueProtect(pCtx, pProperty->m_pCallAsFunction);
|
||||
|
||||
|
||||
PropertyMapRes rsp = m_PropertyMap.insert(PropertyMapValue(name,pProperty));
|
||||
assert(rsp.second);
|
||||
|
||||
FunctionMapRes rsf = m_FunctionMap.insert(FunctionMapValue((unsigned long)pProperty->m_pCallAsFunction,pProperty));
|
||||
assert(rsf.second);
|
||||
|
||||
}
|
||||
void finish( const std::string& name ){
|
||||
m_bIsGlobal = false;
|
||||
finishImpl( name, nullptr);
|
||||
}
|
||||
void finishToGlobal( const std::string& name, T* pIns){
|
||||
assert(pIns != nullptr);
|
||||
m_bIsGlobal = false;
|
||||
finishImpl( name, pIns);
|
||||
m_bIsGlobal = true;
|
||||
}
|
||||
JSObjectRef transferObjPtrToJS( T *p_pIns ){
|
||||
assert( !m_bIsGlobal );
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSObjectRef pRet = JSObjectMake( pCtx, m_ClassObject, p_pIns );
|
||||
p_pIns->mpJsThis = pRet;
|
||||
JSValueRef pProperty = JSValueMakeNumber(pCtx, (double)getTypeID());
|
||||
JSStringRef pszName = JSStringCreateWithUTF8CString(__Js_class_typeid_property);
|
||||
JSObjectSetProperty(pCtx, pRet, pszName, pProperty, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete, 0);
|
||||
JSStringRelease(pszName);
|
||||
|
||||
if( m_FixedProperties.size() ){
|
||||
FixedPropertiesIter iter;
|
||||
for(iter=m_FixedProperties.begin();iter!=m_FixedProperties.end();iter++){
|
||||
JSStringRef sName = (*iter)->GetName();
|
||||
JSObjectSetProperty(pCtx, pRet, sName, (*iter)->GetValue(), kJSPropertyAttributeReadOnly/*|kJSPropertyAttributeDontDelete*/, 0);
|
||||
//kJSPropertyAttributeDontDelete 就意味着这个值不能改了 fuck
|
||||
JSStringRelease(sName);
|
||||
}
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
static void reset(){
|
||||
JSCClass<T>::getInstance()->_reset();
|
||||
}
|
||||
private:
|
||||
static JSObjectRef newWrap(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
if( JSCClass<T>::getInstance()->m_bIsGlobal ){
|
||||
__JsThrow::Throw(exception,"can't new a global object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IJSCCallback *pfn = JSCClass<T>::getInstance()->m_Constructor.get( (int)argumentCount );
|
||||
|
||||
if( 0 == pfn ){
|
||||
return JSCClass<T>::getInstance()->transferObjPtrToJS(new T);
|
||||
}
|
||||
else{
|
||||
return pfn->constructor(ctx, constructor, argumentCount, arguments, exception);
|
||||
}
|
||||
}
|
||||
|
||||
static void destroyWrap(JSObjectRef object){
|
||||
T *p = (T *)JSObjectGetPrivate(object);
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
static bool isInstanceOf(JSContextRef ctx, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception){
|
||||
if( !JSValueIsObject(ctx, possibleInstance) ){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bRet = __CheckClassType::IsTypeOf<T>((JSObjectRef)possibleInstance);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool hasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName){
|
||||
std::string strPropertyName = __TransferToCpp<char *>::ToCpp(propertyName);
|
||||
resetJsStrBuf();
|
||||
if( !strPropertyName.length() ){
|
||||
return false;
|
||||
}
|
||||
|
||||
return (0 != JSCClass<T>::getInstance()->findProperty(strPropertyName.c_str()));
|
||||
}
|
||||
static JSValueRef getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
|
||||
T *pThis = (T *)JSObjectGetPrivate( object );
|
||||
|
||||
if( 0 == pThis ){
|
||||
__JsThrow::Throw(exception,"not a global object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string strPropertyName = __TransferToCpp<char *>::ToCpp(propertyName);
|
||||
resetJsStrBuf();
|
||||
if( !strPropertyName.length() ){
|
||||
__JsThrow::Throw(exception,"GetProperty PropertyName is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CallbackDefine *pProperty = JSCClass<T>::getInstance()->findProperty(strPropertyName.c_str());
|
||||
|
||||
if( 0 == pProperty ){
|
||||
__JsThrow::Throw(exception,"GetProperty can't find property");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSValueRef pRet = NULL;
|
||||
if( CallbackType_Property == pProperty->m_iType ){
|
||||
// is property
|
||||
pRet = pProperty->m_pGetter->call(ctx, nullptr, object, 0, nullptr, nullptr);//?????????????????????
|
||||
}
|
||||
else
|
||||
{ // is function
|
||||
pRet = pProperty->m_pCallAsFunction;
|
||||
}
|
||||
|
||||
return pRet;
|
||||
}
|
||||
static bool setProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception){
|
||||
T *pThis = (T *)JSObjectGetPrivate( object );
|
||||
|
||||
if( 0 == pThis ){
|
||||
__JsThrow::Throw(exception,"not a global object");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sPropertyName = __TransferToCpp<char *>::ToCpp(propertyName);
|
||||
resetJsStrBuf();
|
||||
if( sPropertyName.empty() ){
|
||||
__JsThrow::Throw(exception,"SetProperty PropertyName is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
CallbackDefine *pProperty = JSCClass<T>::getInstance()->findProperty(sPropertyName);
|
||||
|
||||
|
||||
if( 0 == pProperty ){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( CallbackType_Property != pProperty->m_iType )
|
||||
{
|
||||
if( pProperty->m_iType == CallbackType_Function ){
|
||||
JSObjectRef _obj = JSValueToObject(ctx, value, 0);
|
||||
if( JSObjectIsFunction(ctx,_obj) ){
|
||||
getInstance()->JSDefineFunction[sPropertyName] = _obj;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
__JsThrow::Throw(exception,"SetProperty property is function object");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( 0 == pProperty->m_pSetter ){
|
||||
__JsThrow::Throw(exception,"SetProperty property is read only");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSValueRef arguments[1];
|
||||
arguments[0] = value;
|
||||
pProperty->m_pSetter->call(ctx, nullptr, object, 1, arguments, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static JSValueRef callAsFunctionCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
|
||||
T *pThis = (T *)JSObjectGetPrivate( thisObject );
|
||||
|
||||
if( nullptr == pThis ){
|
||||
__JsThrow::Throw(exception,"CallAsFunctionCallback this is null");
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
CallbackDefine *pProperty = JSCClass<T>::getInstance()->findFunction((unsigned long)function);
|
||||
|
||||
if( pProperty != NULL ){
|
||||
JSDefineFunctionIter it = getInstance()->JSDefineFunction.find(pProperty->m_name);
|
||||
if( it != getInstance()->JSDefineFunction.end() ){
|
||||
return JSObjectCallAsFunction(ctx,it->second,thisObject,argumentCount,arguments,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( nullptr == pProperty ){
|
||||
__JsThrow::Throw(exception,"CallAsFunctionCallback can't find function");
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
IJSCCallback *pMethod = pProperty->getMethod(argumentCount);
|
||||
if( 0 != pMethod ){
|
||||
//__JsThrow::GetInstance()->UpdateException(exception);
|
||||
return pMethod->call(ctx, function, thisObject, argumentCount, arguments, exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
__JsThrow::Throw(exception,"callAsFunctionCallback can't find function");
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void _reset(){
|
||||
|
||||
if( m_FixedProperties.size() ){
|
||||
FixedPropertiesIter iter;
|
||||
for(iter=m_FixedProperties.begin();iter!=m_FixedProperties.end();iter++){
|
||||
delete *iter;
|
||||
}
|
||||
m_FixedProperties.clear();
|
||||
}
|
||||
|
||||
for (PropertyMapItr itr = m_PropertyMap.begin(); itr != m_PropertyMap.end(); itr++ ){
|
||||
delete itr->second;
|
||||
}
|
||||
m_PropertyMap.clear();
|
||||
|
||||
m_FunctionMap.clear();
|
||||
|
||||
m_bIsGlobal = false;
|
||||
m_ClassDefine = kJSClassDefinitionEmpty;
|
||||
|
||||
if ( m_ClassObject != nullptr ){
|
||||
JSClassRelease(m_ClassObject);
|
||||
m_ClassObject = nullptr;
|
||||
}
|
||||
JSDefineFunction.clear();
|
||||
|
||||
m_Constructor.reset();
|
||||
}
|
||||
void finishImpl( const std::string& name, T *p_pIns ){
|
||||
|
||||
assert(!name.empty());
|
||||
m_ClassDefine = kJSClassDefinitionEmpty;
|
||||
m_ClassDefine.attributes = kJSClassAttributeNone;
|
||||
m_ClassDefine.className = name.c_str();
|
||||
m_ClassDefine.callAsConstructor = JSCClass<T>::newWrap;
|
||||
m_ClassDefine.finalize = JSCClass<T>::destroyWrap;
|
||||
m_ClassDefine.hasProperty = JSCClass<T>::hasProperty;
|
||||
m_ClassDefine.hasInstance = JSCClass<T>::isInstanceOf;
|
||||
m_ClassDefine.getProperty = JSCClass<T>::getProperty;
|
||||
m_ClassDefine.setProperty = JSCClass<T>::setProperty;
|
||||
m_ClassDefine.callAsFunction = JSCClass<T>::callAsFunctionCallback;
|
||||
|
||||
m_ClassObject = JSClassCreate(&m_ClassDefine);
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
JSStringRef jsName = JSStringCreateWithUTF8CString(name.c_str());
|
||||
JSObjectRef myObject;
|
||||
if( 0 != p_pIns ){
|
||||
myObject = transferObjPtrToJS( p_pIns );
|
||||
p_pIns->mpJsThis = myObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
myObject = JSObjectMake(pCtx, m_ClassObject, 0);
|
||||
}
|
||||
|
||||
JSObjectSetProperty( pCtx, JSContextGetGlobalObject(pCtx), jsName, myObject, kJSPropertyAttributeNone, NULL );//???
|
||||
JSStringRelease(jsName);
|
||||
}
|
||||
CallbackDefine *findFunction( unsigned long p_ulObj ){
|
||||
FunctionMapItr iter = m_FunctionMap.find(p_ulObj);
|
||||
if( iter == m_FunctionMap.end() ){
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*iter).second;
|
||||
}
|
||||
}
|
||||
CallbackDefine *findProperty( const std::string& name ){
|
||||
PropertyMapItr iter = m_PropertyMap.find(name);
|
||||
if( iter == m_PropertyMap.end() ){
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*iter).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
typedef std::unordered_map<std::string,CallbackDefine*> PropertyMap;
|
||||
typedef typename PropertyMap::value_type PropertyMapValue;
|
||||
typedef typename PropertyMap::iterator PropertyMapItr;
|
||||
typedef std::pair<PropertyMapItr,bool> PropertyMapRes;
|
||||
PropertyMap m_PropertyMap;
|
||||
|
||||
typedef std::unordered_map<unsigned long,CallbackDefine*> FunctionMap;
|
||||
typedef typename FunctionMap::value_type FunctionMapValue;
|
||||
typedef typename FunctionMap::iterator FunctionMapItr;
|
||||
typedef std::pair<FunctionMapItr,bool> FunctionMapRes;
|
||||
FunctionMap m_FunctionMap;
|
||||
|
||||
bool m_bIsGlobal;
|
||||
JSClassDefinition m_ClassDefine;
|
||||
JSClassRef m_ClassObject;
|
||||
typedef std::unordered_map<std::string,JSObjectRef>::iterator JSDefineFunctionIter;
|
||||
std::unordered_map<std::string, JSObjectRef> JSDefineFunction;
|
||||
unsigned int m_iTypeID;
|
||||
|
||||
FuncEntry m_Constructor;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,826 @@
|
||||
|
||||
#ifndef _JSCProxyFunction_h
|
||||
#define _JSCProxyFunction_h
|
||||
|
||||
namespace laya
|
||||
{
|
||||
|
||||
template<class T>
|
||||
JSValueRef ToJSValue(T t) {
|
||||
return __TransferToJs<T>::ToJs(t);
|
||||
}
|
||||
|
||||
inline bool checkJSToCArgs(size_t given, size_t expect) {
|
||||
assert(given >= expect);
|
||||
if (given >= expect)
|
||||
return true;
|
||||
static char buff[512];
|
||||
sprintf(buff, "console.log('arguments number err: %d:%d');var e = new Error();console.log(e.stack);", expect, given);
|
||||
//__JSRun::Run(buff);
|
||||
return false;
|
||||
}
|
||||
|
||||
#define JS2CCALL_GET_COBJ \
|
||||
Cls* pThis = (Cls*)JSObjectGetPrivate( thisObject );
|
||||
|
||||
|
||||
#define JS2CCALL_GET_PARAMS1 \
|
||||
if(!checkJSToCArgs(argumentCount,1))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS2 \
|
||||
if(!checkJSToCArgs(argumentCount,2))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS3 \
|
||||
if(!checkJSToCArgs(argumentCount,3))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS4 \
|
||||
if(!checkJSToCArgs(argumentCount,4))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS5 \
|
||||
if(!checkJSToCArgs(argumentCount,5))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS6 \
|
||||
if(!checkJSToCArgs(argumentCount,6))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS7 \
|
||||
if(!checkJSToCArgs(argumentCount,7))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);\
|
||||
P7 p7 = __TransferToCpp<P7>::ToCpp(arguments[6]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS8 \
|
||||
if(!checkJSToCArgs(argumentCount,8))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);\
|
||||
P7 p7 = __TransferToCpp<P7>::ToCpp(arguments[6]);\
|
||||
P8 p8 = __TransferToCpp<P8>::ToCpp(arguments[7]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS9 \
|
||||
if(!checkJSToCArgs(argumentCount,9))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);\
|
||||
P7 p7 = __TransferToCpp<P7>::ToCpp(arguments[6]);\
|
||||
P8 p8 = __TransferToCpp<P8>::ToCpp(arguments[7]);\
|
||||
P9 p9 = __TransferToCpp<P9>::ToCpp(arguments[8]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS11 \
|
||||
if(!checkJSToCArgs(argumentCount,11))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);\
|
||||
P7 p7 = __TransferToCpp<P7>::ToCpp(arguments[6]);\
|
||||
P8 p8 = __TransferToCpp<P8>::ToCpp(arguments[7]);\
|
||||
P9 p9 = __TransferToCpp<P9>::ToCpp(arguments[8]);\
|
||||
P10 p10 = __TransferToCpp<P10>::ToCpp(arguments[9]);\
|
||||
P11 p11 = __TransferToCpp<P11>::ToCpp(arguments[10]);
|
||||
|
||||
#define JS2CCALL_GET_PARAMS12 \
|
||||
if(!checkJSToCArgs(argumentCount,12))return JSValueMakeUndefined(ctx);\
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);\
|
||||
P4 p4 = __TransferToCpp<P4>::ToCpp(arguments[3]);\
|
||||
P5 p5 = __TransferToCpp<P5>::ToCpp(arguments[4]);\
|
||||
P6 p6 = __TransferToCpp<P6>::ToCpp(arguments[5]);\
|
||||
P7 p7 = __TransferToCpp<P7>::ToCpp(arguments[6]);\
|
||||
P8 p8 = __TransferToCpp<P8>::ToCpp(arguments[7]);\
|
||||
P9 p9 = __TransferToCpp<P9>::ToCpp(arguments[8]);\
|
||||
P10 p10 = __TransferToCpp<P10>::ToCpp(arguments[9]);\
|
||||
P11 p11 = __TransferToCpp<P11>::ToCpp(arguments[10]);\
|
||||
P11 p12 = __TransferToCpp<P11>::ToCpp(arguments[11]);
|
||||
|
||||
struct IJSCCallback
|
||||
{
|
||||
virtual ~IJSCCallback(){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){assert(false);return nullptr;}
|
||||
virtual JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){assert(false);return nullptr;}
|
||||
virtual uint16_t getNumArgs() = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct JSCCallback: public IJSCCallback {
|
||||
JSCCallback(T func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
assert(false && "JSCCallback::call not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
};
|
||||
|
||||
template<typename R, typename Cls>
|
||||
struct JSCCallback<R(Cls::*)(void)> :public IJSCCallback{
|
||||
typedef R(Cls::*F)(void);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)());
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
|
||||
template<typename R, typename Cls, typename P1>
|
||||
struct JSCCallback<R(Cls::*)(P1)>: public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS1;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2>//2
|
||||
struct JSCCallback<R(Cls::*)(P1, P2)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS2;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1,p2));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 2; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3>//3
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS3;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2,p3));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 3; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3, typename P4>//4
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3, P4)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3, P4);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS4;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2, p3, p4));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 4; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5>//5
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3, P4, P5)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3, P4, P5);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS5;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2, p3, p4,p5));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 5; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3, P4, P5, P6)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3, P4, P5, P6);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS6;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2, p3, p4, p5,p6));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 6; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS7;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2, p3, p4, p5,p7));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 7; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>//12
|
||||
struct JSCCallback<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)>:public IJSCCallback {
|
||||
typedef R(Cls::*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS12;
|
||||
JSValueRef ret = ToJSValue<R>((pThis->*m_func)(p1, p2, p3, p4, p5, p7, p8, p9, p10, p11, p12));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 12; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
|
||||
template<typename Cls>
|
||||
struct JSCCallback<void(Cls::*)(void)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(void);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
(pThis->*m_func)();
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename P1, typename Cls>//1
|
||||
struct JSCCallback<void(Cls::*)(P1)> :public IJSCCallback{
|
||||
typedef void(Cls::*F)(P1);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS1;
|
||||
(pThis->*m_func)(p1);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename Cls, typename P1, typename P2>//2
|
||||
struct JSCCallback<void(Cls::*)(P1, P2)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS2;
|
||||
(pThis->*m_func)(p1,p2);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 2; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename Cls, typename P1, typename P2, typename P3>//3
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS3;
|
||||
(pThis->*m_func)(p1,p2,p3);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 3; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4>//4
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS4;
|
||||
(pThis->*m_func)(p1, p2, p3, p4);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 4; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5>//5
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS5;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 5; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5, P6)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5, P6);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS6;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5, p6);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 6; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS7;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5, p6, p7);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 7; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>//9
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS9;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 9; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11>//11
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS11;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 11; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>//12
|
||||
struct JSCCallback<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)>:public IJSCCallback {
|
||||
typedef void(Cls::*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
|
||||
JSCCallback(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_COBJ;
|
||||
JS2CCALL_GET_PARAMS12;
|
||||
(pThis->*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 12; }
|
||||
F m_func;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define JS2CCONSTRUCTOR_GET_PARAMS1 \
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);
|
||||
|
||||
#define JS2CCONSTRUCTOR_GET_PARAMS2 \
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);
|
||||
|
||||
#define JS2CCONSTRUCTOR_GET_PARAMS3 \
|
||||
P1 p1 = __TransferToCpp<P1>::ToCpp(arguments[0]);\
|
||||
P2 p2 = __TransferToCpp<P2>::ToCpp(arguments[1]);\
|
||||
P3 p3 = __TransferToCpp<P3>::ToCpp(arguments[2]);
|
||||
|
||||
template<typename Cls>
|
||||
struct JSCConstructor0: public IJSCCallback {
|
||||
virtual JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
return JSCClass<Cls>::getInstance()->transferObjPtrToJS(new Cls());
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
};
|
||||
|
||||
template<typename Cls>
|
||||
IJSCCallback* regConstructor(){
|
||||
return new JSCConstructor0<Cls>();
|
||||
}
|
||||
|
||||
template<typename Cls, typename P1>
|
||||
struct JSCConstructor1:public IJSCCallback{
|
||||
virtual JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCONSTRUCTOR_GET_PARAMS1;
|
||||
return JSCClass<Cls>::getInstance()->transferObjPtrToJS(new Cls(p1));
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
};
|
||||
|
||||
template<typename Cls,typename P1>
|
||||
IJSCCallback* regConstructor(){
|
||||
return new JSCConstructor1<Cls,P1>();
|
||||
}
|
||||
|
||||
template<typename Cls, typename P1,typename P2>
|
||||
struct JSCConstructor2:public IJSCCallback{
|
||||
virtual JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCONSTRUCTOR_GET_PARAMS2;
|
||||
return JSCClass<Cls>::getInstance()->transferObjPtrToJS(new Cls(p1,p2));
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 2; }
|
||||
};
|
||||
|
||||
template<typename Cls,typename P1,typename P2>
|
||||
IJSCCallback* regConstructor(){
|
||||
return new JSCConstructor2<Cls,P1,P2>();
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct IJSCFunction
|
||||
{
|
||||
virtual ~IJSCFunction(){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) = 0;
|
||||
virtual uint16_t getNumArgs() = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct JSCFunction: public IJSCFunction {
|
||||
JSCFunction(T func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
assert(false && "JSCFunction::call not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
};
|
||||
|
||||
template<typename R>//R(void)
|
||||
struct JSCFunction<R(*)(void)>: public IJSCFunction {
|
||||
typedef R(*F)(void);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)());
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1>//R(p1)
|
||||
struct JSCFunction<R(*)(P1)>: public IJSCFunction {
|
||||
typedef R(*F)(P1);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS1;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1>//const R(p1)
|
||||
struct JSCFunction<const R(*)(P1)>:public IJSCFunction {
|
||||
typedef const R(*F)(P1);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS1;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2>//R(p1,p2)
|
||||
struct JSCFunction<R(*)(P1, P2)>: public IJSCFunction {
|
||||
typedef R(*F)(P1,P2);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS2;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 2; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3>//3
|
||||
struct JSCFunction<R(*)(P1, P2, P3)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS3;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 3; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4>//4
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS4;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 4; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>//5
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4, P5)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4, P5);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS5;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4, p5));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 5; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4, P5, P6)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4, P5, P6);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS6;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4, p5, p6));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 6; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4, P5, P6, P7)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS7;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4, p5, p6, p7));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 7; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>//8
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4, P5, P6, P7, P8)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS8;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4, p5, p6, p7, p8));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 8; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>//9
|
||||
struct JSCFunction<R(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)>: public IJSCFunction {
|
||||
typedef R(*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS9;
|
||||
JSValueRef ret = ToJSValue<R>((*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9));
|
||||
resetJsStrBuf();
|
||||
return ret;
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 9; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
//void
|
||||
template<> //void(void)
|
||||
struct JSCFunction<void(*)(void)>: public IJSCFunction {
|
||||
typedef void(*F)(void);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
(*m_func)();
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 0; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1>
|
||||
struct JSCFunction<void(*)(P1)>: public IJSCFunction {//void(p1)
|
||||
typedef void(*F)(P1);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS1;
|
||||
(*m_func)(p1);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 1; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2>//void(p1,p2)
|
||||
struct JSCFunction<void(*)(P1, P2)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS2;
|
||||
(*m_func)(p1, p2);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 2; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename P1, typename P2, typename P3>//3
|
||||
struct JSCFunction<void(*)(P1, P2, P3)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS3;
|
||||
(*m_func)(p1, p2, p3);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 3; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4>//4
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS4;
|
||||
(*m_func)(p1, p2, p3, p4);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 4; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5>//5
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS5;
|
||||
(*m_func)(p1, p2, p3, p4, p5);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 5; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5, P6)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5, P6);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS6;
|
||||
(*m_func)(p1, p2, p3, p4, p5, p6);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 6; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template< typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5, P6, P7)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5, P6, P7);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS7;
|
||||
(*m_func)(p1, p2, p3, p4, p5, p6, p7);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 7; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>//8
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5, P6, P7, P8)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5, P6, P7, P8);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS8;
|
||||
(*m_func)(p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 8; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>//9
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS9;
|
||||
(*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 9; }
|
||||
F m_func;
|
||||
};
|
||||
|
||||
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>//12
|
||||
struct JSCFunction<void(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)>: public IJSCFunction {
|
||||
typedef void(*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
|
||||
JSCFunction(F func):m_func(func){}
|
||||
virtual JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
|
||||
JS2CCALL_GET_PARAMS12;
|
||||
(*m_func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
|
||||
resetJsStrBuf();
|
||||
return JSValueMakeUndefined(ctx);
|
||||
}
|
||||
virtual uint16_t getNumArgs() { return 12; }
|
||||
F m_func;
|
||||
};
|
||||
} // namespace __JSCProxy
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
|
||||
#ifndef _JSCProxyTLS_h
|
||||
#define _JSCProxyTLS_h
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
#include <JavaScriptCore/JSStringRef.h>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
#include "../../../CToObjectC.h"
|
||||
#include <util/JCCommonMethod.h>
|
||||
#include <util/Log.h>
|
||||
#include <pthread.h>
|
||||
namespace laya
|
||||
{
|
||||
class __TlsData
|
||||
{
|
||||
__TlsData(){}
|
||||
~__TlsData(){}
|
||||
public:
|
||||
static pthread_key_t s_tls_curThread;
|
||||
static __TlsData *GetInstance()
|
||||
{
|
||||
static __TlsData _Ins;
|
||||
return &_Ins;
|
||||
}
|
||||
|
||||
void *SetCurContext( JSContextRef p_pContext )
|
||||
{
|
||||
void *pRet = (void *)pthread_getspecific(s_tls_curThread);
|
||||
pthread_setspecific(s_tls_curThread,(void*)p_pContext);
|
||||
return pRet;
|
||||
}
|
||||
|
||||
JSContextRef GetCurContext()
|
||||
{
|
||||
return (JSContextRef)pthread_getspecific(s_tls_curThread);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class __JsThrow
|
||||
{
|
||||
JSValueRef *m_pException;
|
||||
|
||||
public:
|
||||
__JsThrow()
|
||||
{
|
||||
m_pException = 0;
|
||||
}
|
||||
|
||||
static __JsThrow *GetInstance()
|
||||
{
|
||||
static __JsThrow _Ins;
|
||||
return &_Ins;
|
||||
}
|
||||
|
||||
static void Throw( JSValueRef* exception, const char *p_pszInfo=0 )
|
||||
{
|
||||
if( 0 != exception )
|
||||
{
|
||||
JSStringRef message = JSStringCreateWithUTF8CString((0==p_pszInfo)?"unknown error":p_pszInfo);
|
||||
*exception = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), message);
|
||||
JSStringRelease(message);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateException( JSValueRef* exception )
|
||||
{
|
||||
m_pException = exception;
|
||||
}
|
||||
|
||||
void RuntimeThrow( const char *p_pszInfo )
|
||||
{
|
||||
__JsThrow::Throw(m_pException,p_pszInfo);
|
||||
}
|
||||
};
|
||||
extern bool gbAlertException;
|
||||
class __JSRun
|
||||
{
|
||||
static char *__ToCppString( JSValueRef p_vl, JSContextRef p_pContext )
|
||||
{
|
||||
char *pRet = 0;
|
||||
JSStringRef _jsStr = JSValueToStringCopy(p_pContext, p_vl, 0);
|
||||
if( _jsStr )
|
||||
{
|
||||
size_t iSize = JSStringGetMaximumUTF8CStringSize(_jsStr);
|
||||
if(iSize>0)
|
||||
{
|
||||
pRet=new char[iSize+1];
|
||||
JSStringGetUTF8CString( _jsStr, pRet, iSize+1 );
|
||||
}
|
||||
JSStringRelease( _jsStr );
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
public:
|
||||
static void OutputException( JSValueRef exception )
|
||||
{
|
||||
if( NULL != exception )
|
||||
{
|
||||
JSContextRef pContext = __TlsData::GetInstance()->GetCurContext();
|
||||
|
||||
JSStringRef jsLinePropertyName = JSStringCreateWithUTF8CString("line");
|
||||
JSStringRef jsColumnPropertyName = JSStringCreateWithUTF8CString("column");
|
||||
JSStringRef jsUrlPropertyName = JSStringCreateWithUTF8CString("sourceURL");
|
||||
JSObjectRef exObject = JSValueToObject( pContext, exception, NULL );
|
||||
JSValueRef line = JSObjectGetProperty( pContext, exObject, jsLinePropertyName, NULL );
|
||||
JSValueRef column = JSObjectGetProperty( pContext, exObject, jsColumnPropertyName, NULL );
|
||||
JSValueRef url = JSObjectGetProperty( pContext, exObject, jsUrlPropertyName, NULL );
|
||||
char *pEx = __ToCppString(exception,pContext);
|
||||
char *pLine = __ToCppString(line,pContext);
|
||||
char *pColumn = __ToCppString(column,pContext);
|
||||
char *pUrl = __ToCppString(url,pContext);
|
||||
|
||||
//通知全局错误处理脚本
|
||||
|
||||
std::string kBuf = "if(conch.onerror){conch.onerror('";
|
||||
kBuf += UrlEncode(pEx);
|
||||
kBuf += "','undefined','";
|
||||
kBuf += UrlEncode(pLine);
|
||||
kBuf += "','";
|
||||
kBuf += UrlEncode(pColumn);
|
||||
kBuf += "','";
|
||||
kBuf += UrlEncode(pEx);
|
||||
kBuf += "');};";
|
||||
__JSRun::Run(kBuf.c_str());
|
||||
|
||||
static char sBuffer[10240]={0};
|
||||
sprintf( sBuffer,"exception info: [%s] at line %s\n", pEx, pLine );
|
||||
|
||||
if (gbAlertException)
|
||||
CToObjectCAlert( sBuffer );
|
||||
else {
|
||||
LOGE("==JSERROR:\n%s", sBuffer);
|
||||
}
|
||||
|
||||
delete[] pEx;
|
||||
delete[] pLine;
|
||||
delete[] pColumn;
|
||||
delete[] pUrl;
|
||||
JSStringRelease(jsLinePropertyName);
|
||||
JSStringRelease(jsColumnPropertyName);
|
||||
JSStringRelease(jsUrlPropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Run( const char *p_pszScript,JSValueRef* result = NULL )
|
||||
{
|
||||
bool bRet = true;
|
||||
|
||||
JSContextRef pContext = __TlsData::GetInstance()->GetCurContext();
|
||||
JSStringRef pScript = JSStringCreateWithUTF8CString( p_pszScript );
|
||||
|
||||
JSValueRef exception = NULL;
|
||||
JSValueRef ret = JSEvaluateScript(pContext, pScript, NULL, NULL, 0, &exception );
|
||||
if( 0 != exception )
|
||||
{
|
||||
OutputException( exception );
|
||||
bRet = false;
|
||||
}
|
||||
if( ret != NULL && result != NULL ){
|
||||
*result = ret;
|
||||
}
|
||||
JSStringRelease( pScript );
|
||||
|
||||
return bRet;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,443 @@
|
||||
|
||||
#ifndef _JSCProxyTrnasfer_h
|
||||
#define _JSCProxyTrnasfer_h
|
||||
|
||||
#include <JavaScriptCore/JSContextRef.h>
|
||||
#include <JavaScriptCore/JSStringRef.h>
|
||||
#include <JavaScriptCore/JSValueRef.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "JSCProxyTLS.h"
|
||||
#include "JSCProxyType.h"
|
||||
|
||||
|
||||
namespace laya
|
||||
{
|
||||
void resetJsStrBuf();
|
||||
|
||||
template <typename T>class JSCClass;
|
||||
|
||||
template <typename T> class __TransferToCpp
|
||||
{
|
||||
public:
|
||||
static T ToCpp( JSValueRef p_vl ){
|
||||
assert(false && "type not supported!");
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
return __CheckClassType::IsTypeOf<T>(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class __TransferToCpp<T*>
|
||||
{
|
||||
public:
|
||||
static T* ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
if( 0 == p_vl || JSValueIsUndefined(pCtx, p_vl) || JSValueIsNull(pCtx, p_vl) )
|
||||
return nullptr;
|
||||
else
|
||||
return (T*)JSObjectGetPrivate((JSObjectRef)p_vl);
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
return __CheckClassType::IsTypeOf<T>(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> class __TransferToCpp<int>
|
||||
{
|
||||
public:
|
||||
static int ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (int)JSValueToNumber(pCtx,p_vl,0);
|
||||
else return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<short>
|
||||
{
|
||||
public:
|
||||
static int ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (short)JSValueToNumber(pCtx,p_vl,0);
|
||||
else return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> class __TransferToCpp<unsigned int>
|
||||
{
|
||||
public:
|
||||
static unsigned int ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (unsigned int)JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<long>
|
||||
{
|
||||
public:
|
||||
static long ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (long)JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<unsigned long>
|
||||
{
|
||||
public:
|
||||
static unsigned long ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (unsigned long)JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<bool>
|
||||
{
|
||||
public:
|
||||
static bool ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return JSValueToBoolean(pCtx,p_vl);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsBoolean(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<float>
|
||||
{
|
||||
public:
|
||||
static float ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (float)JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<double>
|
||||
{
|
||||
public:
|
||||
static double ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<long long>
|
||||
{
|
||||
public:
|
||||
static long long ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)
|
||||
return (long long)JSValueToNumber(pCtx,p_vl,0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<unsigned long long>
|
||||
{
|
||||
public:
|
||||
static unsigned long long ToCpp( JSValueRef p_vl ){
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0!=p_vl)return (unsigned long long)JSValueToNumber(pCtx,p_vl,0);
|
||||
else return 0;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
return JSValueIsNumber(pCtx, p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> class __TransferToCpp<JSValueRef>
|
||||
{
|
||||
public:
|
||||
static JSValueRef ToCpp( JSValueRef p_vl ){
|
||||
return p_vl;
|
||||
}
|
||||
static bool is( JSValueRef p_vl ){
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
char* JsCharToC(JSValueRef p_vl);
|
||||
char* JsCharToC(JSStringRef p_vl);
|
||||
#define __DeclareStringTransferToCpp(Tp) \
|
||||
template <> class __TransferToCpp<Tp> \
|
||||
{ \
|
||||
public: \
|
||||
static char *ToCpp( JSValueRef p_vl ) \
|
||||
{ \
|
||||
return JsCharToC(p_vl); \
|
||||
} \
|
||||
static char *ToCpp( JSStringRef p_vl ) \
|
||||
{ \
|
||||
return JsCharToC(p_vl); \
|
||||
} \
|
||||
static std::string ToCppStd( JSValueRef p_vl ) \
|
||||
{ \
|
||||
return JsCharToC(p_vl); \
|
||||
} \
|
||||
static std::string ToCppStd( JSStringRef p_vl ) \
|
||||
{ \
|
||||
return JsCharToC(p_vl); \
|
||||
} \
|
||||
static bool is( JSValueRef p_vl ){ \
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext(); \
|
||||
return JSValueIsString(pCtx, p_vl); \
|
||||
} \
|
||||
};
|
||||
|
||||
__DeclareStringTransferToCpp(char *);
|
||||
__DeclareStringTransferToCpp(const char *);
|
||||
__DeclareStringTransferToCpp(unsigned char *);
|
||||
__DeclareStringTransferToCpp(const unsigned char *);
|
||||
|
||||
|
||||
template <typename T> class __TransferToJs
|
||||
{
|
||||
public:
|
||||
static JSValueRef ToJs( T *p_vl ){
|
||||
return JSCClass<T>::getInstance()->transferObjPtrToJS(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<void>
|
||||
{public:static JSValueRef ToJs( int p_vl )
|
||||
{
|
||||
JSContextRef pCtx=__TlsData::GetInstance()->GetCurContext();
|
||||
if(0==p_vl)
|
||||
return JSValueMakeUndefined(pCtx);
|
||||
else
|
||||
return JSValueMakeNull(pCtx);
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<JSValueRef>
|
||||
{public:static JSValueRef ToJs( JSValueRef p_vl ){return p_vl;}};
|
||||
|
||||
|
||||
template <> class __TransferToJs<bool>
|
||||
{public:static JSValueRef ToJs( bool p_vl ){return JSValueMakeBoolean(__TlsData::GetInstance()->GetCurContext(),p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<int>
|
||||
{public:static JSValueRef ToJs( int p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<unsigned int>
|
||||
{public:static JSValueRef ToJs( unsigned int p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<float>
|
||||
{public:static JSValueRef ToJs( float p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<double>
|
||||
{public:static JSValueRef ToJs( double p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<long long>
|
||||
{
|
||||
public:
|
||||
static JSValueRef ToJs( long long p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}
|
||||
|
||||
static JSValueRef ToJsDate( long long p_vl )
|
||||
{
|
||||
JSValueRef n = ToJs(p_vl);
|
||||
return JSObjectMakeDate(__TlsData::GetInstance()->GetCurContext(), 1, &n, 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<long>
|
||||
{
|
||||
public:
|
||||
static JSValueRef ToJs( long p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}
|
||||
|
||||
static JSValueRef ToJsDate( long p_vl )
|
||||
{
|
||||
JSValueRef n = ToJs(p_vl);
|
||||
return JSObjectMakeDate(__TlsData::GetInstance()->GetCurContext(), 1, &n, 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<unsigned long long>
|
||||
{
|
||||
public:
|
||||
static JSValueRef ToJs( unsigned long long p_vl ){return JSValueMakeNumber(__TlsData::GetInstance()->GetCurContext(),(double)p_vl);}
|
||||
|
||||
static JSValueRef ToJsDate( unsigned long long p_vl )
|
||||
{
|
||||
JSValueRef n = ToJs(p_vl);
|
||||
return JSObjectMakeDate(__TlsData::GetInstance()->GetCurContext(), 1, &n, 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<char *>
|
||||
{public:static JSValueRef ToJs( char *p_vl )
|
||||
{
|
||||
JSStringRef pStr = JSStringCreateWithUTF8CString(p_vl);
|
||||
JSValueRef pRet = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), pStr);
|
||||
JSStringRelease(pStr);
|
||||
return pRet;
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<const char *>
|
||||
{public:static JSValueRef ToJs( const char *p_vl )
|
||||
{
|
||||
JSStringRef pStr = JSStringCreateWithUTF8CString(p_vl);
|
||||
JSValueRef pRet = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), pStr);
|
||||
JSStringRelease(pStr);
|
||||
return pRet;
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<unsigned char *>
|
||||
{public:static JSValueRef ToJs( unsigned char *p_vl )
|
||||
{
|
||||
JSStringRef pStr = JSStringCreateWithUTF8CString((char *)p_vl);
|
||||
JSValueRef pRet = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), pStr);
|
||||
JSStringRelease(pStr);
|
||||
return pRet;
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<const unsigned char *>
|
||||
{public:static JSValueRef ToJs( const unsigned char *p_vl )
|
||||
{
|
||||
JSStringRef pStr = JSStringCreateWithUTF8CString((char *)p_vl);
|
||||
JSValueRef pRet = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), pStr);
|
||||
JSStringRelease(pStr);
|
||||
return pRet;
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<std::string>
|
||||
{public:static JSValueRef ToJs( std::string p_vl )
|
||||
{
|
||||
JSStringRef pStr = JSStringCreateWithUTF8CString(p_vl.c_str());
|
||||
JSValueRef pRet = JSValueMakeString(__TlsData::GetInstance()->GetCurContext(), pStr);
|
||||
JSStringRelease(pStr);
|
||||
return pRet;
|
||||
}};
|
||||
|
||||
template <typename T> class __JsArray{
|
||||
public:
|
||||
static JSObjectRef ToJsArray(const std::vector<T*>& p_vl)
|
||||
{
|
||||
int p_iSize = p_vl.size();
|
||||
|
||||
JSValueRef pValArray[p_iSize];
|
||||
for(int i=0;i<p_iSize;++i)
|
||||
{
|
||||
pValArray[i] = __TransferToJs<T>::ToJs(p_vl[i]);
|
||||
}
|
||||
|
||||
JSObjectRef pRet = JSObjectMakeArray( __TlsData::GetInstance()->GetCurContext(), p_iSize, pValArray, 0 );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
static JSObjectRef ToJsArray(const std::vector<T>& p_vl)
|
||||
{
|
||||
|
||||
int p_iSize = p_vl.size();
|
||||
|
||||
JSValueRef pValArray[p_iSize];
|
||||
for(int i=0;i<p_iSize;++i)
|
||||
{
|
||||
pValArray[i] = __TransferToJs<T>::ToJs(p_vl[i]);
|
||||
}
|
||||
|
||||
JSObjectRef pRet = JSObjectMakeArray( __TlsData::GetInstance()->GetCurContext(), p_iSize, pValArray, 0 );
|
||||
return pRet;
|
||||
}
|
||||
};
|
||||
|
||||
class __JsByteArray
|
||||
{
|
||||
public:
|
||||
static JSObjectRef ToJsByteArray( const unsigned char *p_vl, int p_iSize )
|
||||
{
|
||||
if( 0 == p_vl || p_iSize <= 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
JSValueRef pValArray[p_iSize];
|
||||
for(int i=0;i<p_iSize;++i)
|
||||
{
|
||||
pValArray[i] = __TransferToJs<unsigned int>::ToJs(p_vl[i]);
|
||||
}
|
||||
|
||||
JSObjectRef pRet = JSObjectMakeArray( __TlsData::GetInstance()->GetCurContext(), p_iSize, pValArray, 0 );
|
||||
return pRet;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T> class __TransferToJs<std::vector<T*> >
|
||||
{
|
||||
public:static JSObjectRef ToJs( const std::vector<T*>& p_vl )
|
||||
{
|
||||
return __JsArray<T>::ToJsArray(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class __TransferToJs<std::vector<T> >
|
||||
{
|
||||
public:static JSObjectRef ToJs(const std::vector<T>& p_vl)
|
||||
{
|
||||
return __JsArray<T>::ToJsArray(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
#ifndef __JSCProxyType_h
|
||||
#define __JSCProxyType_h
|
||||
#define NDEBUG
|
||||
#include <assert.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
|
||||
|
||||
|
||||
#define __Js_class_typeid_property "__cppclstypeid"
|
||||
|
||||
namespace laya
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
__VT_void = 0,
|
||||
__VT_string,
|
||||
__VT_bool,
|
||||
__VT_int,
|
||||
__VT_long,
|
||||
__VT_float,
|
||||
__VT_double,
|
||||
__VT_longlong,
|
||||
__VT_ArrayBuffer,
|
||||
__VT_object,
|
||||
} __ValueType;
|
||||
|
||||
template <class _Key> struct __InferType
|
||||
{__ValueType iType;__InferType(){iType=__VT_object;}};
|
||||
|
||||
template<> struct __InferType<void>
|
||||
{__ValueType iType;__InferType(){iType=__VT_void;}};
|
||||
|
||||
template<> struct __InferType<bool>
|
||||
{__ValueType iType;__InferType(){iType=__VT_bool;}};
|
||||
|
||||
template<> struct __InferType<char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<const char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<unsigned char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<const unsigned char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<int>
|
||||
{__ValueType iType;__InferType(){iType=__VT_int;}};
|
||||
|
||||
template<> struct __InferType<unsigned int>
|
||||
{__ValueType iType;__InferType(){iType=__VT_int;}};
|
||||
|
||||
template<> struct __InferType<long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_long;}};
|
||||
|
||||
template<> struct __InferType<unsigned long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_long;}};
|
||||
|
||||
template<> struct __InferType<float>
|
||||
{__ValueType iType;__InferType(){iType=__VT_float;}};
|
||||
|
||||
template<> struct __InferType<double>
|
||||
{__ValueType iType;__InferType(){iType=__VT_double;}};
|
||||
|
||||
template<> struct __InferType<long long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
|
||||
|
||||
template<> struct __InferType<unsigned long long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
|
||||
|
||||
template<typename T>
|
||||
class JSCClass;
|
||||
|
||||
class __CheckClassType
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
static bool IsTypeOf( JSObjectRef p_pObj )
|
||||
{
|
||||
if( 0 == p_pObj )
|
||||
return false;
|
||||
|
||||
JSStringRef pszName = JSStringCreateWithUTF8CString(__Js_class_typeid_property);
|
||||
JSValueRef pProperty = JSObjectGetProperty(__TlsData::GetInstance()->GetCurContext(), p_pObj, pszName, 0);
|
||||
JSStringRelease(pszName);
|
||||
|
||||
if( 0 == pProperty )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
int nID = (int)JSValueToNumber(pCtx,pProperty,0);
|
||||
|
||||
return (nID == (JSCClass<T>::getInstance()->getTypeID()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool IsTypeOf( JSValueRef p_pVal )
|
||||
{
|
||||
if( 0 == p_pVal )
|
||||
return false;
|
||||
|
||||
JSContextRef pCtx = __TlsData::GetInstance()->GetCurContext();
|
||||
if( !JSValueIsObject(pCtx, p_pVal) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsTypeOf<T>((JSObjectRef)p_pVal);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace __JSCProxy
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
@file JSInterface.cpp
|
||||
@brief
|
||||
@author wyw
|
||||
@version 1.0
|
||||
@date 2014_7_29
|
||||
*/
|
||||
|
||||
#include "JSInterface.h"
|
||||
#ifdef JS_JSC
|
||||
//#include <JavaScriptCore/JSBasePrivate.h>
|
||||
#endif
|
||||
|
||||
namespace laya
|
||||
{
|
||||
void AdjustAmountOfExternalAllocatedMemory(int p_nMemorySize)
|
||||
{
|
||||
#ifdef JS_V8
|
||||
v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(p_nMemorySize);
|
||||
#elif JS_JSC
|
||||
//JSReportExtraMemoryCost(__TlsData::GetInstance()->GetCurContext(), p_nMemorySize);
|
||||
#endif
|
||||
}
|
||||
JsValue getNativeObj(JSValueAsParam p_pJsObj, char* p_strName)
|
||||
{
|
||||
#ifdef JS_V8
|
||||
if (p_pJsObj->IsObject()) {
|
||||
v8::Local<v8::Object> pobj = v8::Local<v8::Object>::Cast(p_pJsObj);
|
||||
JsValue nativeObj = pobj->Get(JSP_TO_JS(char*, p_strName));
|
||||
if (!nativeObj.IsEmpty() && nativeObj->IsObject()) {
|
||||
return nativeObj;
|
||||
}
|
||||
}
|
||||
return p_pJsObj;
|
||||
#elif JS_JSC
|
||||
JSContextRef ctx = __TlsData::GetInstance()->GetCurContext();
|
||||
if (JSValueIsObject(ctx, p_pJsObj)) {
|
||||
JSObjectRef obj = JSValueToObject(ctx, p_pJsObj, nullptr);
|
||||
if (obj != nullptr) {
|
||||
JSStringRef name = JSStringCreateWithUTF8CString(p_strName);
|
||||
JSValueRef ret = JSObjectGetProperty(ctx, obj, name, nullptr);
|
||||
JSStringRelease(name);
|
||||
if (!JSValueIsNull(ctx, ret) && !JSValueIsUndefined(ctx, ret)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p_pJsObj;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
@file JSInterface.h
|
||||
@brief
|
||||
@author wyw
|
||||
@version 1.0
|
||||
@date 2013_12_2
|
||||
*/
|
||||
|
||||
#ifndef __JSInterface_H__
|
||||
#define __JSInterface_H__
|
||||
|
||||
#include <JSObjBase.h>
|
||||
#include <util/JCMemorySurvey.h>
|
||||
#ifdef JS_JSC
|
||||
#include "JSC/JSCBinder.h"
|
||||
#include "JSC/JSCEnv.h"
|
||||
#include "JSC/JSCArrayBuffer.h"
|
||||
#elif JS_V8
|
||||
#include <v8.h>
|
||||
#include "V8/JSEnv.h"
|
||||
#include "V8/JSArrayBuffer.h"
|
||||
#include "V8/JsBinder.h"
|
||||
#endif
|
||||
|
||||
namespace laya
|
||||
{
|
||||
#ifdef JS_JSC
|
||||
struct JsFuncArgs {};
|
||||
typedef JSValueRef JSValueAsParam;
|
||||
typedef JSValueRef JsValue;
|
||||
typedef JsObjHandleJSC JsObjHandle;
|
||||
#define JSP_RESET_GLOBAL_FUNCTION JSCGlobal::getInstance()->reset()
|
||||
#define JS_TO_CPP(tp,v) laya::__TransferToCpp<tp>::ToCpp(v)
|
||||
#define JSP_TO_JS_BYTE_ARRAY(vl,sz) (laya::__JsByteArray::ToJsByteArray(vl,sz))
|
||||
#define JSP_TO_JS(tp,v) (laya::__TransferToJs<tp>::ToJs(v))
|
||||
#define JSP_TO_JS_NULL JSP_TO_JS(void,1)
|
||||
#define JSP_TO_JS_UNDEFINE JSP_TO_JS(void,0)
|
||||
#define JSP_THROW(str) (laya::__JsThrow::GetInstance()->RuntimeThrow(str))
|
||||
#define JSP_RUN_SCRIPT(script) (laya::__JSRun::Run(script))
|
||||
#define JSP_TO_JS_STR(str) (laya::__TransferToJs<const char*>::ToJs(str))
|
||||
class JsObjBase : public JSObjBaseJSC {};
|
||||
#define JS_TRY
|
||||
#define JS_CATCH
|
||||
#elif JS_V8
|
||||
class JsObjBase :public JSObjBaseV8
|
||||
{
|
||||
};
|
||||
#define JSValueAsParam JsValue
|
||||
typedef JsObjHandle2 JsObjHandle;
|
||||
#define JSP_THROW(str) __JsThrow:: Throw(str);
|
||||
#define JSP_RUN_SCRIPT(script) __JSRun::Run(script);
|
||||
#define JSP_TO_JS_NULL ((v8::Null(v8::Isolate::GetCurrent())))
|
||||
#define JSP_TO_JS_UNDEFINE ((v8::Undefined(v8::Isolate::GetCurrent())))
|
||||
#include "V8/JSCProxyTrnasfer.h"
|
||||
#define JSP_TO_JS_BYTE_ARRAY(vl,sz) (__JsByteArray::ToJsByteArray(vl,sz))
|
||||
#define JSP_TO_JS(tp,v) (__TransferToJs<tp>::ToJs(v))
|
||||
#define JS_TO_CPP(tp,v) (__TransferToCpp<tp>::ToCpp(v))
|
||||
#define JSP_TO_JS_STR(str) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),str))
|
||||
#define JS_TRY \
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();\
|
||||
v8::HandleScope handle_scope(isolate);\
|
||||
v8::TryCatch try_catch(isolate);
|
||||
|
||||
#define JS_CATCH \
|
||||
if (try_catch.HasCaught()){\
|
||||
LOGE("JS onFrame error\n");\
|
||||
__JSRun::ReportException(isolate, &try_catch);\
|
||||
}
|
||||
#endif
|
||||
void AdjustAmountOfExternalAllocatedMemory(int p_nMemorySize);
|
||||
JsValue getNativeObj(JSValueAsParam p_pJsObj, char* p_strName);
|
||||
|
||||
}
|
||||
#endif //__JSInterface_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,264 @@
|
||||
#ifdef JS_V8
|
||||
|
||||
#include "JSArrayBuffer.h"
|
||||
#include <util/JCMemorySurvey.h>
|
||||
#include <util/Log.h>
|
||||
#include "../JSInterface.h"
|
||||
#include "JSCProxyTrnasfer.h"
|
||||
|
||||
namespace laya {
|
||||
//TODO 这里没有考虑多线程的问题,如果js要支持多线程的话,需要修改。
|
||||
struct JsStrBuff {
|
||||
char* _buff;
|
||||
int _len;
|
||||
static std::vector<JsStrBuff> jsstrbuffs;
|
||||
static int curIdx;
|
||||
JsStrBuff() {
|
||||
_buff = NULL;
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
static JsStrBuff& getAData() {
|
||||
if (JsStrBuff::curIdx >= (int)JsStrBuff::jsstrbuffs.size()) {
|
||||
JsStrBuff::jsstrbuffs.push_back(JsStrBuff());
|
||||
JsStrBuff::curIdx++;
|
||||
return JsStrBuff::jsstrbuffs.back();
|
||||
}
|
||||
else {
|
||||
return JsStrBuff::jsstrbuffs[JsStrBuff::curIdx++];
|
||||
}
|
||||
}
|
||||
};
|
||||
std::vector<JsStrBuff> JsStrBuff::jsstrbuffs;
|
||||
int JsStrBuff::curIdx = 0;
|
||||
|
||||
//
|
||||
void resetJsStrBuf() {
|
||||
JsStrBuff::curIdx = 0;
|
||||
}
|
||||
char* JsCharToC(Local<Value> p_vl) {
|
||||
int len = 0;
|
||||
Local<String> str = p_vl->ToString();
|
||||
len = str->Utf8Length();
|
||||
if (len <= 0)
|
||||
return "";
|
||||
JsStrBuff& curdata = JsStrBuff::getAData();
|
||||
char*& tocharBuf = curdata._buff;
|
||||
int& tocharBufLen = curdata._len;
|
||||
|
||||
//tocharBuf= new char[len + 1];
|
||||
if (len > tocharBufLen) {
|
||||
tocharBufLen = len;
|
||||
if (tocharBuf != NULL)
|
||||
delete[] tocharBuf;
|
||||
tocharBuf = new char[len+1];
|
||||
}
|
||||
else {
|
||||
//如果占用空间太大,也要重新分配
|
||||
if (tocharBufLen > 1024 ) {
|
||||
tocharBufLen = len;
|
||||
if (tocharBuf != NULL)
|
||||
delete[] tocharBuf;
|
||||
tocharBuf = new char[len+1];
|
||||
}
|
||||
}
|
||||
str->WriteUtf8(tocharBuf);
|
||||
return tocharBuf;
|
||||
}
|
||||
}
|
||||
|
||||
namespace laya{
|
||||
ArrayBufferAllocator::ArrayBufferAllocator() {
|
||||
}
|
||||
|
||||
ArrayBufferAllocator::~ArrayBufferAllocator() {
|
||||
}
|
||||
|
||||
void* ArrayBufferAllocator::Allocate(size_t length) {
|
||||
char* pRet = new char[length];
|
||||
memset(pRet,0,length);
|
||||
return pRet;
|
||||
}
|
||||
void* ArrayBufferAllocator::AllocateUninitialized(size_t length){
|
||||
char* pRet = new char[length];
|
||||
return pRet;
|
||||
};
|
||||
void ArrayBufferAllocator::Free(void* data, size_t length)
|
||||
{
|
||||
if (data != NULL || length > 0)
|
||||
{
|
||||
delete[]((char*)data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGI("ArrayBufferAllocator::Free data=%d length=%d",(intptr_t)data, length);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayBufferAllocator* ArrayBufferAllocator::getInstance(){
|
||||
return new ArrayBufferAllocator();
|
||||
}
|
||||
|
||||
v8::Local<v8::ArrayBuffer> createJSAB(char* pData, int len) {
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), len);
|
||||
v8::ArrayBuffer::Contents contents = ab->GetContents();// ab->Externalize();
|
||||
char* pPtr = (char*)contents.Data();
|
||||
memcpy(pPtr, pData, len);
|
||||
//Externalize 以后会减去内存占用,导致不能正确GC,所以再给加回来。不知道管理ArrayBuffer的正确方法是什么。
|
||||
//v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(len);
|
||||
return ab;
|
||||
}
|
||||
|
||||
v8::Local<v8::ArrayBuffer> createJSABAligned(char* pData, int len) {
|
||||
int asz = (len + 3) & 0xfffffffc;
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), asz);
|
||||
v8::ArrayBuffer::Contents contents = ab->GetContents();// ab->Externalize();
|
||||
char* pPtr = (char*)contents.Data();
|
||||
memcpy(pPtr, pData, len);
|
||||
//ArrayBuffer 自己已经初始化为0了
|
||||
//Externalize 以后会减去内存占用,导致不能正确GC,所以再给加回来。不知道管理ArrayBuffer的正确方法是什么。
|
||||
//v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(asz);
|
||||
return ab;
|
||||
}
|
||||
|
||||
bool extractJSAB(JsValue jsval, char*& data, int& len) {
|
||||
v8::Local<v8::ArrayBuffer> ab;
|
||||
if (jsval->IsArrayBufferView()) {
|
||||
v8::Local<v8::ArrayBufferView> abv = v8::Local<v8::ArrayBufferView>::Cast(jsval);
|
||||
len = abv->ByteLength();
|
||||
ab = abv->Buffer();
|
||||
v8::ArrayBuffer::Contents contents = ab->GetContents();
|
||||
//len = contents.ByteLength(); 这种情况下,用view的长度,因为可能多个view公用一个大buffer
|
||||
data = (char*)contents.Data()+abv->ByteOffset();
|
||||
}
|
||||
else if (jsval->IsArrayBuffer()) {
|
||||
ab = v8::Local<v8::ArrayBuffer>::Cast(jsval);
|
||||
v8::ArrayBuffer::Contents contents = ab->GetContents();
|
||||
len = contents.ByteLength();
|
||||
data = (char*)contents.Data();
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (ab->IsExternal()) {
|
||||
v8::ArrayBuffer::Contents contents = ab->GetContents();
|
||||
len = contents.ByteLength();
|
||||
data = (char*)contents.Data();
|
||||
}
|
||||
else {
|
||||
v8::ArrayBuffer::Contents contents = ab->Externalize();
|
||||
len = contents.ByteLength();
|
||||
v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(len);
|
||||
data = (char*)contents.Data();
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void __JSRun::ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::String::Utf8Value exception(try_catch->Exception());
|
||||
const char* exception_string = ToCString(exception);
|
||||
v8::Handle<v8::Message> message = try_catch->Message();
|
||||
static char errInfo[2048];
|
||||
int curpos = 0;
|
||||
if (message.IsEmpty()) {
|
||||
// V8 didn't provide any extra information about this error; just
|
||||
// print the exception.
|
||||
int off = snprintf(errInfo, sizeof(errInfo), "%s\n", exception_string);
|
||||
|
||||
//通知全局错误处理脚本
|
||||
std::string kBuf = "if(conch.onerror){conch.onerror('";
|
||||
kBuf += UrlEncode(exception_string);
|
||||
kBuf += "','undefined','undefined','undefined','";
|
||||
kBuf += UrlEncode(exception_string);
|
||||
kBuf += "');};";
|
||||
__JSRun::Run(kBuf.c_str());
|
||||
}
|
||||
else {
|
||||
auto ctx = isolate->GetCurrentContext();
|
||||
v8::String::Utf8Value fnstr (message->GetScriptResourceName());
|
||||
const char* filename_string = ToCString(fnstr);
|
||||
v8::MaybeLocal<String> source_line_maybe = message->GetSourceLine(ctx);
|
||||
v8::String::Utf8Value srclinestr(source_line_maybe.ToLocalChecked());
|
||||
const char* sourceline_string = ToCString(srclinestr);
|
||||
int linenum = message->GetLineNumber(ctx).FromJust();
|
||||
int start = message->GetStartColumn(ctx).FromMaybe(0);
|
||||
int end = message->GetEndColumn(ctx).FromMaybe(0);
|
||||
v8::ScriptOrigin origin = message->GetScriptOrigin();
|
||||
int lineoff = origin.ResourceLineOffset()->Value();
|
||||
int startcol = origin.ResourceColumnOffset()->Value();
|
||||
if (start > startcol) {
|
||||
start -= startcol;
|
||||
end -= startcol;
|
||||
}
|
||||
|
||||
//错误行可能非常长,只取一部分
|
||||
char errLineSrc[128];
|
||||
if (strlen(sourceline_string) > 128) {
|
||||
int startoff = start > 50 ? (start - 50) : 0;
|
||||
start -= startoff;
|
||||
end -= startoff;
|
||||
if (end >= 128)end = 127;
|
||||
|
||||
memcpy(errLineSrc, sourceline_string+startoff, 128);
|
||||
sourceline_string = errLineSrc;
|
||||
}
|
||||
curpos += snprintf(errInfo, sizeof(errInfo), "%s:%i:\n%s\n%s\n",
|
||||
filename_string,
|
||||
linenum,
|
||||
exception_string,
|
||||
sourceline_string);
|
||||
//打印具体哪一行,哪一列
|
||||
if (curpos < sizeof(errInfo)) {
|
||||
int st = curpos;
|
||||
int srclen = snprintf(errInfo + curpos, sizeof(errInfo) - curpos, "%s\n", sourceline_string);
|
||||
curpos += srclen;
|
||||
if (curpos < sizeof(errInfo)) {
|
||||
for (int si = 0; si < srclen; si++) {
|
||||
char& c = errInfo[st+si];
|
||||
if (c != ' ' && c != '\t' && c != '\r')c = ' ';
|
||||
if (si >= start && si <= end)c = '^';
|
||||
}
|
||||
}
|
||||
}
|
||||
curpos += snprintf(errInfo + curpos,sizeof(errInfo)-curpos, "\n");
|
||||
v8::String::Utf8Value stack_trace(try_catch->StackTrace());
|
||||
if (stack_trace.length() > 0) {
|
||||
const char* stack_trace_string = ToCString(stack_trace);
|
||||
if (curpos < sizeof(errInfo)) {
|
||||
curpos += snprintf(errInfo + curpos,sizeof(errInfo)-curpos, "%s", stack_trace_string);
|
||||
}
|
||||
}
|
||||
|
||||
//通知全局错误处理脚本
|
||||
std::string kBuf = "if(conch.onerror){conch.onerror('";
|
||||
kBuf += UrlEncode(exception_string);
|
||||
kBuf += "','";
|
||||
kBuf += UrlEncode(filename_string);
|
||||
kBuf += "','";
|
||||
//kBuf += std::to_string(linenum);
|
||||
std::ostringstream os;
|
||||
os << linenum;
|
||||
kBuf += os.str();
|
||||
kBuf += "','";
|
||||
kBuf += "undefined";
|
||||
kBuf += "','";
|
||||
kBuf += UrlEncode(errInfo);
|
||||
kBuf += "');};";
|
||||
__JSRun::Run(kBuf.c_str());
|
||||
|
||||
}
|
||||
|
||||
if (gbAlertException)
|
||||
JSAlert(errInfo);
|
||||
else {
|
||||
LOGE("==JSERROR:\n%s", errInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
#ifndef _JS_ARRAYBUFFER_H_
|
||||
#define _JS_ARRAYBUFFER_H_
|
||||
|
||||
#include <v8.h>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
如果有c这边的ArrayBufferView引用这个ArrayBuffer的话,需要增加引用计数,不能直接删除
|
||||
*/
|
||||
|
||||
namespace laya{
|
||||
|
||||
//这个要在v8线程外分配和释放,因为v8析构的时候会调用这个对象提供的 Free 接口
|
||||
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
|
||||
public:
|
||||
ArrayBufferAllocator();
|
||||
~ArrayBufferAllocator();
|
||||
virtual void* Allocate(size_t length) ;
|
||||
virtual void* AllocateUninitialized(size_t length);
|
||||
virtual void Free(void* data, size_t length);
|
||||
//这个函数没有意义,v8本身会都释放掉 Heap::FreeDeadArrayBuffers
|
||||
//void FreeAllAlive();//释放所有的还没有释放的ArrayBuffer
|
||||
static ArrayBufferAllocator* getInstance();
|
||||
//int _testGetID(void* pdata);
|
||||
//int getAliveBufferNum() {
|
||||
// return m_vAliveBuffer.size();
|
||||
//}
|
||||
protected:
|
||||
//std::vector<char*> m_vAliveBuffer;
|
||||
};
|
||||
|
||||
v8::Local<v8::ArrayBuffer> createJSAB(char* pData, int len);
|
||||
v8::Local<v8::ArrayBuffer> createJSABAligned(char* pData, int len);
|
||||
bool extractJSAB(v8::Local<v8::Value> ab, char*& data, int& len);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// JSCProxyTLS.h
|
||||
// jsc_test
|
||||
//
|
||||
// Created by 蒋 宇彤 on 13-11-25.
|
||||
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef jsc_test_JSCProxyTLS_h
|
||||
#define jsc_test_JSCProxyTLS_h
|
||||
|
||||
#include <v8.h>
|
||||
#include <string>
|
||||
#include <util/JCCommonMethod.h>
|
||||
#include <util/Log.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace laya{
|
||||
extern void JSAlert(const char* p_sBuffer);
|
||||
class __JsThrow {
|
||||
public:
|
||||
static void Throw( const char *p_pszInfo ) {
|
||||
v8::Isolate::GetCurrent()->ThrowException(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), (0==p_pszInfo)?"unknown error":p_pszInfo));
|
||||
}
|
||||
};
|
||||
extern bool gbAlertException;
|
||||
class __JSRun {
|
||||
public:
|
||||
// Extracts a C string from a V8 Utf8Value.
|
||||
static const char* ToCString(const v8::String::Utf8Value& value) {
|
||||
return *value ? *value : "<string conversion failed>";
|
||||
}
|
||||
|
||||
static void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch);
|
||||
|
||||
static bool Run( const char *p_pszScript ) {
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::TryCatch try_catch(isolate);
|
||||
|
||||
v8::Handle<v8::String> source = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), p_pszScript);
|
||||
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile(source);
|
||||
if( script.IsEmpty() ){
|
||||
//打印编译错误信息
|
||||
printf("---Compile script error---\n");
|
||||
ReportException(isolate, &try_catch);
|
||||
return false;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> res = script->Run();
|
||||
|
||||
if( !res.IsEmpty() && !res->IsUndefined() )
|
||||
{
|
||||
v8::String::Utf8Value ascii(res);
|
||||
printf("run result: [%s]\n", *ascii);
|
||||
}
|
||||
|
||||
if( try_catch.HasCaught()){
|
||||
printf("---run script error---\n");
|
||||
ReportException(isolate, &try_catch);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,402 @@
|
||||
//
|
||||
// JSCProxyTrnasfer.h
|
||||
// jsc_test
|
||||
//
|
||||
// Created by 蒋 宇彤 on 13-11-25.
|
||||
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef jsc_test_JSCProxyTrnasfer_h
|
||||
#define jsc_test_JSCProxyTrnasfer_h
|
||||
|
||||
#include <v8.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "JSArrayBuffer.h"
|
||||
//#include "JsBinder.h"
|
||||
|
||||
using namespace v8;
|
||||
namespace laya{
|
||||
//为了能快速返回js的字符串,现在转字符串的函数使用了通用buffer,
|
||||
//为了能同时返回多个buffer指针,就用了一个vector,为了避免vector一直增加,内存泄露
|
||||
//就用了这个函数。具体看代码。
|
||||
void resetJsStrBuf();
|
||||
|
||||
template<class T>
|
||||
Local<Object> createJsObjAttachCObj(T* cobj, bool weak);
|
||||
|
||||
template <typename T> class __TransferToCpp{public:
|
||||
static T ToCpp( Local<Value> p_vl ){
|
||||
// 这是很危险的
|
||||
if( !p_vl.IsEmpty() && p_vl->IsObject() ){
|
||||
return static_cast<T>((p_vl.As<Object>())->GetAlignedPointerFromInternalField(0));
|
||||
}else{
|
||||
return (T)0;
|
||||
}
|
||||
}
|
||||
//问题:如果是对象的话,当请求 T或者T* 认为是相同的
|
||||
static bool is(Local<Value> p_vl) {
|
||||
if (!p_vl->IsObject())
|
||||
return false;
|
||||
Local<Object> obj = p_vl.As<Object>();
|
||||
if (obj->InternalFieldCount() < 2)
|
||||
return false;
|
||||
void* pdt = obj->GetAlignedPointerFromInternalField(1);
|
||||
if( pdt == &T::JSCLSINFO) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//不知道怎么区分对象和对象指针,先硬写一个
|
||||
template <typename T> class __TransferToCpp<T*> {
|
||||
public:
|
||||
static T* ToCpp(Local<Value> p_vl) {
|
||||
// 这是很危险的
|
||||
if (!p_vl.IsEmpty() && p_vl->IsObject()) {
|
||||
Local<Object> obj = p_vl.As<Object>();
|
||||
return static_cast<T*>(obj->GetAlignedPointerFromInternalField(0));
|
||||
}
|
||||
else {
|
||||
return (T*)0;
|
||||
}
|
||||
}
|
||||
//问题:如果是对象的话,当请求 T或者T* 认为是相同的
|
||||
static bool is(Local<Value> p_vl) {
|
||||
if (!p_vl->IsObject())
|
||||
return false;
|
||||
Local<Object> obj = p_vl.As<Object>();
|
||||
void* pdt = obj->GetAlignedPointerFromInternalField(1);
|
||||
if (pdt == &T::JSCLSINFO) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<int32_t> {
|
||||
public:
|
||||
static int32_t ToCpp(Local<Value> p_vl) { return p_vl->Int32Value(); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<int64_t> {
|
||||
public:
|
||||
static int64_t ToCpp(Local<Value> p_vl) { return p_vl->IntegerValue(); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<uint32_t> {
|
||||
public:
|
||||
static uint32_t ToCpp(Local<Value> p_vl) { return p_vl->Uint32Value(); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<uint64_t> {
|
||||
public:
|
||||
static uint64_t ToCpp(Local<Value> p_vl) { return (uint64_t)p_vl->IntegerValue(); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
};
|
||||
|
||||
// template <> class __TransferToCpp<int>{public:
|
||||
// static int ToCpp( Local<Value> p_vl ){return p_vl->Int32Value();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
|
||||
//};
|
||||
|
||||
//template <> class __TransferToCpp<short> {public:
|
||||
// static short ToCpp(Local<Value> p_vl) { return p_vl->Int32Value(); }
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
|
||||
//};
|
||||
|
||||
// template <> class __TransferToCpp<unsigned int> {public:
|
||||
// static unsigned int ToCpp( Local<Value> p_vl ){return p_vl->Uint32Value();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
|
||||
//};
|
||||
|
||||
// template <> class __TransferToCpp<long>{public:
|
||||
// static long ToCpp( Local<Value> p_vl ){return p_vl->Int32Value();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsInt32(); }
|
||||
//};
|
||||
|
||||
// template <> class __TransferToCpp<unsigned long>{public:
|
||||
// static unsigned long ToCpp( Local<Value> p_vl ){return p_vl->Uint32Value();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsUint32(); }
|
||||
//};
|
||||
|
||||
template <> class __TransferToCpp<bool>{public:
|
||||
static bool ToCpp( Local<Value> p_vl ){return p_vl->BooleanValue();}
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsBoolean(); }
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<float>{public:
|
||||
static float ToCpp( Local<Value> p_vl ){return (float)p_vl->NumberValue();}
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<double>{public:
|
||||
static double ToCpp( Local<Value> p_vl ){return p_vl->NumberValue();}
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
};
|
||||
|
||||
// template <> class __TransferToCpp<long long>{public:
|
||||
// static long long ToCpp( Local<Value> p_vl ){return p_vl->IntegerValue();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
//};
|
||||
|
||||
// template <> class __TransferToCpp<unsigned long long>{public:
|
||||
// static unsigned long long ToCpp( Local<Value> p_vl ){return (unsigned long long)p_vl->IntegerValue();}
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsNumber(); }
|
||||
//};
|
||||
|
||||
template <> class __TransferToCpp<Local<Value>>{public:
|
||||
static Local<Value> ToCpp(Local<Value> p_vl) { return p_vl; }
|
||||
static bool is(Local<Value> p_vl) { return true; }
|
||||
};
|
||||
|
||||
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制。
|
||||
//这个函数必须配合 resetJsStrBuf 函数使用。
|
||||
//例如
|
||||
// char* p1 = JsCharToC(args[0]);
|
||||
// char* p2 = JsCharToC(args[1]);
|
||||
// use(p1,p2);
|
||||
// resetJsStrBuf();
|
||||
char* JsCharToC(Local<Value> p_vl);
|
||||
class transToCharPtr {
|
||||
public:
|
||||
static char *ToCpp1(Local<Value> p_vl) {
|
||||
String::Utf8Value utf8str(p_vl->ToString());
|
||||
//return *utf8str;
|
||||
//下面有泄露
|
||||
char *pRet = 0;
|
||||
size_t len;
|
||||
if (0 != *utf8str && 0 != (len = strlen(*utf8str))){
|
||||
pRet = new char[len + 1];
|
||||
memcpy(pRet, *utf8str, len + 1);
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
static std::string ToCppStd(Local<Value> p_vl) {
|
||||
String::Utf8Value utf8str(p_vl->ToString());
|
||||
return std::string(*utf8str);
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToCpp<char *> {public:
|
||||
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
|
||||
static char* ToCpp(Local<Value> p_vl) { return JsCharToC(p_vl); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
|
||||
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
|
||||
};
|
||||
template <> class __TransferToCpp<const char *> {public:
|
||||
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
|
||||
static const char* ToCpp(Local<Value> p_vl) { return (const char*)JsCharToC(p_vl); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
|
||||
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
|
||||
};
|
||||
template <> class __TransferToCpp<unsigned char *> {public:
|
||||
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
|
||||
static unsigned char* ToCpp(Local<Value> p_vl) { return (unsigned char*)JsCharToC(p_vl); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
|
||||
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
|
||||
};
|
||||
template <> class __TransferToCpp<const unsigned char *> {public:
|
||||
//注意:这个函数返回的字符串使用了一个通用buffer,所以注意复制
|
||||
static const unsigned char* ToCpp(Local<Value> p_vl) { return (const unsigned char*)JsCharToC(p_vl); }
|
||||
static bool is(Local<Value> p_vl) { return p_vl->IsString(); }
|
||||
static std::string ToCppStd(Local<Value> p_vl) { return transToCharPtr::ToCppStd(p_vl); }
|
||||
};
|
||||
|
||||
//template<> class __TransferToCpp<laya::JSArrayBuffer*>{public:
|
||||
// static bool is(Local<Value> p_vl) { return p_vl->IsArrayBuffer() || p_vl->IsArrayBufferView(); }
|
||||
// static laya::JSArrayBuffer* ToCpp(Local<Value> p_vl) { return laya::JSArrayBuffer::fromeJSObj(p_vl); };
|
||||
//};
|
||||
|
||||
template <typename T> class __TransferToJs{
|
||||
public:static Handle<Value> ToJs(T* p_vl) {
|
||||
return laya::createJsObjAttachCObj<T>(p_vl,true);
|
||||
}
|
||||
};
|
||||
|
||||
//为什么不直接把没有参数作为void?
|
||||
template <> class __TransferToJs<void>
|
||||
{public:static Handle<Value> ToJs( int p_vl )
|
||||
{
|
||||
if(0==p_vl)
|
||||
return Undefined(Isolate::GetCurrent());
|
||||
else
|
||||
return Null(Isolate::GetCurrent());
|
||||
}};
|
||||
|
||||
template <> class __TransferToJs<v8::Local<v8::Value>>{
|
||||
public:static Handle<Value> ToJs(v8::Local<v8::Value> p_vl) { return p_vl; }
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<v8::Local<v8::Object> >
|
||||
{
|
||||
public:static Handle<Value> ToJs(v8::Local<v8::Object> p_vl) { return p_vl; }
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<bool>
|
||||
{public:static Handle<Value> ToJs( bool p_vl ){return Boolean::New(Isolate::GetCurrent(),p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<int>
|
||||
{public:static Handle<Value> ToJs( int p_vl ){return Int32::New(Isolate::GetCurrent(), p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<unsigned int>
|
||||
{public:static Handle<Value> ToJs( unsigned int p_vl ){return Uint32::New(Isolate::GetCurrent(), p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<long unsigned int>
|
||||
{
|
||||
public:static Handle<Value> ToJs(long unsigned int p_vl) { return Number::New(Isolate::GetCurrent(), p_vl); }
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<float>
|
||||
{public:static Handle<Value> ToJs( float p_vl ){return Number::New(Isolate::GetCurrent(), p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<double>
|
||||
{public:static Handle<Value> ToJs( double p_vl ){return Number::New(Isolate::GetCurrent(), p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<long long>
|
||||
{
|
||||
public:
|
||||
static Handle<Value> ToJs( long long p_vl )
|
||||
{
|
||||
return Number::New(Isolate::GetCurrent(), (double)p_vl);
|
||||
}
|
||||
|
||||
static Handle<Value> ToJsDate( long long p_vl )
|
||||
{
|
||||
return Date::New(Isolate::GetCurrent(), (double)p_vl );
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<long>
|
||||
{
|
||||
public:
|
||||
static Handle<Value> ToJs( long p_vl )
|
||||
{
|
||||
return Number::New(Isolate::GetCurrent(), (double)p_vl);
|
||||
}
|
||||
|
||||
static Handle<Value> ToJsDate( long p_vl )
|
||||
{
|
||||
return Date::New(Isolate::GetCurrent(), (double)p_vl );
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<unsigned long long>
|
||||
{
|
||||
public:
|
||||
static Handle<Value> ToJs( unsigned long long p_vl )
|
||||
{
|
||||
return Number::New(Isolate::GetCurrent(), (double)p_vl);
|
||||
}
|
||||
|
||||
static Handle<Value> ToJsDate( unsigned long long p_vl )
|
||||
{
|
||||
return Date::New(Isolate::GetCurrent(), (double)p_vl );
|
||||
}
|
||||
};
|
||||
|
||||
template <> class __TransferToJs<char *>
|
||||
{public:static Handle<Value> ToJs( char *p_vl ){if(p_vl==0) p_vl=(char*)""; return String::NewFromUtf8(Isolate::GetCurrent(),p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<const char *>
|
||||
{public:static Handle<Value> ToJs( const char *p_vl ){if(p_vl==0) p_vl=(const char *)""; return String::NewFromUtf8(Isolate::GetCurrent(),p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<unsigned char *>
|
||||
{public:static Handle<Value> ToJs( const unsigned char*p_vl ){if(p_vl==0) p_vl=(const unsigned char*)""; return String::NewFromUtf8(Isolate::GetCurrent(),(const char *)p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<const unsigned char *>
|
||||
{public:static Handle<Value> ToJs( const unsigned char *p_vl ){if(p_vl==0) p_vl=(const unsigned char *)""; return String::NewFromUtf8(Isolate::GetCurrent(),(const char *)p_vl);}};
|
||||
|
||||
template <> class __TransferToJs<std::string>
|
||||
{public:static Handle<Value> ToJs( std::string p_vl ){return String::NewFromUtf8(Isolate::GetCurrent(), p_vl.c_str());}};
|
||||
|
||||
template <> class __TransferToJs<std::string&> {
|
||||
public:static Handle<Value> ToJs(std::string& p_vl) { return String::NewFromUtf8(Isolate::GetCurrent(), p_vl.c_str()); }
|
||||
};
|
||||
//template <> class __TransferToJs<laya::JSArrayBuffer*>
|
||||
//{public:static Handle<Value> ToJs( laya::JSArrayBuffer* p_vl ){return p_vl->toLocal();}};
|
||||
template <typename T> class __JsArray{
|
||||
public:
|
||||
static Handle<Value> ToJsArray(const std::vector<T*>& p_v1)
|
||||
{
|
||||
int size=p_v1.size();
|
||||
if(0==size)
|
||||
{
|
||||
Handle<Array> __array = Array::New(Isolate::GetCurrent(), 0);
|
||||
return __array;
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle<Array> __array = Array::New(Isolate::GetCurrent(), size);
|
||||
for(int i=0;i<size;i++)
|
||||
{
|
||||
//__array->Set(i, __JSCProxy_class<T>::GetInstance()->TransferObjPtrToJS(p_v1.at(i)));
|
||||
__array->Set(i, __TransferToJs<T>::ToJs(p_v1.at(i)));
|
||||
}
|
||||
return __array;
|
||||
}
|
||||
}
|
||||
static Handle<Value> ToJsArray(const std::vector<T>& p_v1)
|
||||
{
|
||||
int size = p_v1.size();
|
||||
if (0 == size)
|
||||
{
|
||||
Handle<Array> __array = Array::New(Isolate::GetCurrent(), 0);
|
||||
return __array;
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle<Array> __array = Array::New(Isolate::GetCurrent(), size);
|
||||
for (int i = 0; i<size; i++)
|
||||
{
|
||||
//__array->Set(i, __JSCProxy_class<T>::GetInstance()->TransferObjPtrToJS(p_v1.at(i)));
|
||||
__array->Set(i, __TransferToJs<T>::ToJs(p_v1.at(i)));
|
||||
}
|
||||
return __array;
|
||||
}
|
||||
}
|
||||
};
|
||||
class __JsByteArray
|
||||
{
|
||||
public:
|
||||
static Handle<Value> ToJsByteArray( const unsigned char *p_vl, int p_iSize )
|
||||
{
|
||||
if( 0 == p_vl || p_iSize <= 0 )
|
||||
{
|
||||
return Null(Isolate::GetCurrent());
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle<Array> __array = Array::New(Isolate::GetCurrent(), p_iSize);
|
||||
for(int i=0;i<p_iSize;++i)
|
||||
{
|
||||
__array->Set( i, Int32::New(Isolate::GetCurrent(), p_vl[i]) );
|
||||
}
|
||||
return __array;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class __TransferToJs<std::vector<T*> >
|
||||
{
|
||||
public:static Handle<Value> ToJs( const std::vector<T*>& p_vl )
|
||||
{
|
||||
return __JsArray<T>::ToJsArray(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class __TransferToJs<std::vector<T> >
|
||||
{
|
||||
public:static Handle<Value> ToJs(const std::vector<T>& p_vl)
|
||||
{
|
||||
return __JsArray<T>::ToJsArray(p_vl);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// JSCProxyType.h
|
||||
// jsc_test
|
||||
//
|
||||
// Created by 蒋 宇彤 on 13-12-1.
|
||||
// Copyright (c) 2013年 蒋 宇彤. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef jsc_test_JSCProxyType_h
|
||||
#define jsc_test_JSCProxyType_h
|
||||
|
||||
#include <v8.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
|
||||
namespace laya{
|
||||
typedef enum {
|
||||
__VT_void = 0,
|
||||
__VT_string,
|
||||
__VT_bool,
|
||||
__VT_int,
|
||||
__VT_long,
|
||||
__VT_float,
|
||||
__VT_double,
|
||||
__VT_longlong,
|
||||
__VT_ArrayBuffer,
|
||||
__VT_object,
|
||||
} __ValueType;
|
||||
|
||||
template <class _Key> struct __InferType
|
||||
{__ValueType iType;__InferType(){iType=__VT_object;}};
|
||||
|
||||
template<> struct __InferType<void>
|
||||
{__ValueType iType;__InferType(){iType=__VT_void;}};
|
||||
|
||||
template<> struct __InferType<bool>
|
||||
{__ValueType iType;__InferType(){iType=__VT_bool;}};
|
||||
|
||||
template<> struct __InferType<char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<const char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<unsigned char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<const unsigned char *>
|
||||
{__ValueType iType;__InferType(){iType=__VT_string;}};
|
||||
|
||||
template<> struct __InferType<int>
|
||||
{__ValueType iType;__InferType(){iType=__VT_int;}};
|
||||
|
||||
template<> struct __InferType<unsigned int>
|
||||
{__ValueType iType;__InferType(){iType=__VT_int;}};
|
||||
|
||||
template<> struct __InferType<long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_long;}};
|
||||
|
||||
template<> struct __InferType<unsigned long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_long;}};
|
||||
|
||||
template<> struct __InferType<float>
|
||||
{__ValueType iType;__InferType(){iType=__VT_float;}};
|
||||
|
||||
template<> struct __InferType<double>
|
||||
{__ValueType iType;__InferType(){iType=__VT_double;}};
|
||||
|
||||
template<> struct __InferType<long long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
|
||||
|
||||
template<> struct __InferType<unsigned long long>
|
||||
{__ValueType iType;__InferType(){iType=__VT_longlong;}};
|
||||
|
||||
|
||||
class __CheckClassType
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
static bool IsTypeOf( v8::Local<v8::Value> p_Obj )
|
||||
{
|
||||
if( p_Obj.IsEmpty() || !p_Obj->IsObject() )
|
||||
return false;
|
||||
else {
|
||||
v8::Local<v8::Object> obj = p_Obj.As<v8::Object>();
|
||||
void* pdt = v8::Local<v8::External>::Cast(obj->GetInternalField(1))->Value();
|
||||
return pdt == &T::JSCLSINFO;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace __JSCProxy
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
@file JSEnv.cpp
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2018_8_23
|
||||
*/
|
||||
#ifdef JS_V8
|
||||
#include "JSEnv.h"
|
||||
#include <v8-profiler.h>
|
||||
#include "../../v8debug/debug-agent.h"
|
||||
#include "util/Log.h"
|
||||
#include "JSCProxyTLS.h"
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#endif
|
||||
//#define V8PROFILE
|
||||
|
||||
namespace laya
|
||||
{
|
||||
v8::Persistent<v8::Context> Javascript::m_DebugMessageContext;
|
||||
const char* ToCString(const v8::String::Utf8Value& value)
|
||||
{
|
||||
return *value ? *value : "<string conversion failed>";
|
||||
}
|
||||
class LayaHandleScope :public v8::HandleScope
|
||||
{
|
||||
public:
|
||||
LayaHandleScope(v8::Isolate* piso)
|
||||
{
|
||||
HandleScope::Initialize(piso);
|
||||
}
|
||||
~LayaHandleScope()
|
||||
{
|
||||
}
|
||||
public:
|
||||
void Initialize(v8::Isolate* isolate)
|
||||
{
|
||||
HandleScope::Initialize(isolate);
|
||||
}
|
||||
};
|
||||
Javascript::Javascript()
|
||||
{
|
||||
m_pIsolate = NULL;
|
||||
m_pPlatform = NULL;
|
||||
m_pScope = NULL;
|
||||
m_pHandleScope = NULL;
|
||||
m_pV8Locker = NULL;
|
||||
m_pABAlloc = NULL;
|
||||
m_nListenPort = 0;
|
||||
}
|
||||
void Javascript::init(int nPort)
|
||||
{
|
||||
if (!m_pPlatform)
|
||||
{
|
||||
m_pPlatform = v8::platform::CreateDefaultPlatform();
|
||||
v8::V8::InitializePlatform(m_pPlatform);
|
||||
}
|
||||
v8::V8::Initialize();
|
||||
m_nListenPort = 0;
|
||||
if(nPort > 0 && nPort <0xFFFF )
|
||||
{
|
||||
m_nListenPort = nPort;
|
||||
}
|
||||
}
|
||||
void Javascript::uninit()
|
||||
{
|
||||
//不能在v8线程
|
||||
return;
|
||||
if (0 != m_pIsolate)
|
||||
{
|
||||
m_pIsolate->Dispose();
|
||||
m_pIsolate = 0;
|
||||
ArrayBufferAllocator* pABAlloc = ArrayBufferAllocator::getInstance();
|
||||
//pABAlloc->FreeAllAlive();
|
||||
delete pABAlloc;
|
||||
}
|
||||
}
|
||||
void Javascript::initJSEngine()
|
||||
{
|
||||
v8::Isolate::CreateParams create_params;
|
||||
m_pABAlloc = ArrayBufferAllocator::getInstance();
|
||||
create_params.array_buffer_allocator = m_pABAlloc;
|
||||
m_pIsolate = v8::Isolate::New(create_params);
|
||||
static char* flags[] =
|
||||
{
|
||||
"--expose_gc",
|
||||
"--allow-natives-syntax",//导出内部的%函数
|
||||
//"--trace-gc-verbose",
|
||||
//"--use-strict",
|
||||
//"--harmony",
|
||||
//"--print-bytecode", //
|
||||
//"--print-bytecode-filter errf1"
|
||||
//"--trace-ignition-codegen",
|
||||
//"--debug-code",
|
||||
//"--trace-opt",
|
||||
//"--trace-deopt",
|
||||
//"--prof",
|
||||
//"--code-comments",
|
||||
};
|
||||
for (auto f : flags)
|
||||
{
|
||||
v8::V8::SetFlagsFromString(f, strlen(f));
|
||||
}
|
||||
#ifdef V8PROFILE
|
||||
v8::V8::SetFlagsFromString("--prof", 6);
|
||||
char* pSingleLogFile = "--no-logfile_per_isolate";
|
||||
v8::V8::SetFlagsFromString(pSingleLogFile, strlen(pSingleLogFile));
|
||||
#ifdef ANDROID
|
||||
char* profFile = "--logfile /sdcard/lr2perf/v8.log";
|
||||
#elif WIN32
|
||||
char* profFile = "--logfile d:/temp/v8.log";
|
||||
#endif
|
||||
v8::V8::SetFlagsFromString(profFile, strlen(profFile));
|
||||
#endif
|
||||
//m_pLocker = new v8::Locker(m_pIsolate);
|
||||
|
||||
//这个{}是为了能让 Scope起作用
|
||||
m_pScope = new v8::Isolate::Scope(m_pIsolate);
|
||||
m_pHandleScope = (v8::HandleScope*)malloc(sizeof(v8::HandleScope));
|
||||
new (m_pHandleScope) LayaHandleScope(m_pIsolate);
|
||||
v8::Handle<v8::ObjectTemplate> pGlobalTemplate = v8::ObjectTemplate::New(m_pIsolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(m_pIsolate, NULL, pGlobalTemplate, v8::Handle<v8::Value>());
|
||||
context->Enter();
|
||||
//v8::CpuProfiler* pCpuProf = m_pIsolate->GetCpuProfiler();
|
||||
//pCpuProf->StartCpuProfiling(v8::String::New(""));
|
||||
//pCpuProf->StopCpuProfiling(v8::String::New(""));
|
||||
if (m_nListenPort > 0)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> __guard(m_Lock);
|
||||
if (m_DebugMessageContext.IsEmpty())
|
||||
{
|
||||
m_DebugMessageContext.Reset(m_pIsolate, v8::Local<v8::Context>::New(m_pIsolate, context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Javascript::uninitJSEngine()
|
||||
{
|
||||
//当js线程要结束的时候,关闭调试,否则调试器客户端在线程结束后再发送调试事件,会导致非法。
|
||||
if (m_nListenPort > 0)
|
||||
{
|
||||
//v8::Debug::DisableAgent();
|
||||
}
|
||||
if (!m_DebugMessageContext.IsEmpty())
|
||||
{
|
||||
m_DebugMessageContext.Reset();
|
||||
}
|
||||
//应该调用退出,但是context在scope中,先不退出了,发现也没有内存泄漏
|
||||
//context->Enter();
|
||||
delete m_pHandleScope;
|
||||
m_pHandleScope = NULL;
|
||||
delete m_pScope;
|
||||
m_pScope = NULL;
|
||||
m_pIsolate->Dispose();
|
||||
delete m_pABAlloc;
|
||||
}
|
||||
void Javascript::run(const char* sSource, std::function<void(void)> preRunFunc)
|
||||
{
|
||||
}
|
||||
void Javascript::run(const char* sSource)
|
||||
{
|
||||
}
|
||||
void Javascript::run(voidfun func, void* pdata)
|
||||
{
|
||||
v8::TryCatch try_catch(m_pIsolate);
|
||||
func(pdata);
|
||||
if (try_catch.HasCaught())
|
||||
{
|
||||
v8::String::Utf8Value exceptioninfo(try_catch.Exception());
|
||||
printf("Exception info [%s]\n", *exceptioninfo);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
JSV8Worker::JSV8Worker()
|
||||
{
|
||||
|
||||
}
|
||||
JSV8Worker::~JSV8Worker()
|
||||
{
|
||||
|
||||
}
|
||||
void JSV8Worker::_defRunLoop()
|
||||
{
|
||||
#ifdef WIN32
|
||||
{
|
||||
DWORD thid = GetCurrentThreadId();
|
||||
SetNameInternal(thid, m_strName.c_str());
|
||||
//threadInfoLog("start thread:%s,%d", m_strName.c_str(), thid);
|
||||
}
|
||||
#elif ANDROID
|
||||
{
|
||||
//threadInfoLog("start thread:%s,%ld", m_strName.c_str(), gettidv1());
|
||||
}
|
||||
#endif
|
||||
//开始事件
|
||||
JCEventEmitter::evtPtr startEvt(new JCEventBase);
|
||||
startEvt->m_nID = JCWorkerThread::Event_threadStart;
|
||||
emit(startEvt);
|
||||
JCWorkerThread::runObj task;
|
||||
while (!m_bStop)
|
||||
{
|
||||
v8::TryCatch trycatch(v8::Isolate::GetCurrent());
|
||||
if (!m_funcLoop)
|
||||
{
|
||||
//现在的waitdata返回false不再表示要退出。事件唤醒流程
|
||||
if (m_ThreadTasks.WaitData(&task))
|
||||
task();
|
||||
}
|
||||
else
|
||||
{
|
||||
//固定循环流程
|
||||
runQueue();
|
||||
if (!m_funcLoop())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trycatch.HasCaught())
|
||||
{
|
||||
v8::Isolate* piso = v8::Isolate::GetCurrent();
|
||||
if( piso )__JSRun::ReportException(piso, &trycatch);
|
||||
}
|
||||
}
|
||||
//退出事件
|
||||
JCEventEmitter::evtPtr stopEvt(new JCEventBase);
|
||||
stopEvt->m_nID = JCWorkerThread::Event_threadStop;
|
||||
emit(stopEvt);
|
||||
}
|
||||
void call_JSThread__defRunLoop(void* pdata)
|
||||
{
|
||||
JSV8Worker* pthis=(JSV8Worker*)pdata;
|
||||
pthis->_defRunLoop();
|
||||
}
|
||||
void JSV8Worker::_runLoop()
|
||||
{
|
||||
m_pJS->initJSEngine();
|
||||
m_pJS->run(call_JSThread__defRunLoop,this);
|
||||
m_pJS->uninitJSEngine();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
@file JSEnv.h
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2018_8_23
|
||||
*/
|
||||
|
||||
#ifndef __JSEnv_H__
|
||||
#define __JSEnv_H__
|
||||
|
||||
#include <v8.h>
|
||||
#include <libplatform/libplatform.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <misc/JCWorkerThread.h>
|
||||
#include <util/ListNode.h>
|
||||
#include "JSArrayBuffer.h"
|
||||
#include <util/Log.h>
|
||||
#include "JSCProxyTLS.h"
|
||||
|
||||
namespace laya
|
||||
{
|
||||
void JSPrint( const char* p_sBuffer );
|
||||
void JSAlert( const char* p_sBuffer );
|
||||
void evalJS( const char* p_sSource );
|
||||
const char* ToCString(const v8::String::Utf8Value& value);
|
||||
|
||||
class Javascript
|
||||
{
|
||||
public:
|
||||
typedef std::recursive_mutex _MutexType;
|
||||
|
||||
typedef void(*voidfun)(void* data);
|
||||
|
||||
Javascript();
|
||||
|
||||
void init(int nPort);
|
||||
|
||||
//在init之后,并且在js线程的情况下,可以添加js导出
|
||||
//执行一段脚本。并立即退出。
|
||||
void run(const char* sSource );
|
||||
|
||||
//preRunFunc 是在执行脚本之前先执行的函数,例如可以做导出对象
|
||||
void run(const char* sSource, std::function<void(void)> preRunFunc );
|
||||
|
||||
//执行一个函数。并立即退出
|
||||
void run(voidfun func,void* pdata);
|
||||
|
||||
//不能在v8线程,在js退出后,可以进行js对象的清理
|
||||
void uninit();
|
||||
|
||||
void initJSEngine();
|
||||
|
||||
void uninitJSEngine();
|
||||
|
||||
public:
|
||||
static v8::Persistent<v8::Context> m_DebugMessageContext;
|
||||
v8::Isolate* m_pIsolate;
|
||||
v8::Platform* m_pPlatform;
|
||||
v8::Isolate::Scope* m_pScope;
|
||||
v8::HandleScope* m_pHandleScope;
|
||||
v8::Locker* m_pV8Locker;
|
||||
ArrayBufferAllocator* m_pABAlloc;
|
||||
_MutexType m_Lock;
|
||||
int m_nListenPort;
|
||||
};
|
||||
|
||||
|
||||
class JSThreadInterface
|
||||
{
|
||||
public:
|
||||
JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual ~JSThreadInterface()
|
||||
{
|
||||
|
||||
}
|
||||
virtual void post(std::function<void(void)> func) = 0;
|
||||
virtual void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void initialize(int nPort) = 0;
|
||||
virtual void uninitialize() = 0;
|
||||
virtual void setLoopFunc(std::function<bool(void)> func) = 0;
|
||||
virtual void pushDbgFunc(std::function<void(void)> task) = 0;
|
||||
virtual void runDbgFuncs() = 0;
|
||||
virtual void waitAndRunDbgFuncs() = 0;
|
||||
virtual bool hasDbgFuncs() = 0;
|
||||
virtual JCWorkerThread* getWorker() = 0;
|
||||
virtual void run(Javascript::voidfun func,void* pData) = 0;
|
||||
virtual void clearFunc() = 0;
|
||||
};
|
||||
|
||||
class JSV8Worker : public JCWorkerThread
|
||||
{
|
||||
public:
|
||||
|
||||
JSV8Worker();
|
||||
|
||||
~JSV8Worker();
|
||||
|
||||
//因为要trycatch,所以只好再抄一份了
|
||||
virtual void _defRunLoop();
|
||||
|
||||
virtual void _runLoop();
|
||||
|
||||
public:
|
||||
|
||||
Javascript* m_pJS;
|
||||
|
||||
};
|
||||
|
||||
//把Javascript对象放到一个单独的线程中执行。
|
||||
class JSMulThread: public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
|
||||
JSMulThread()
|
||||
{
|
||||
m_kWorker.setThreadName("JavaScript Main");
|
||||
m_kWorker.m_pJS = &m_kJS;
|
||||
}
|
||||
|
||||
~JSMulThread()
|
||||
{
|
||||
//uninitialize();
|
||||
}
|
||||
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
m_kWorker.post(func);
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread=0)
|
||||
{
|
||||
m_kWorker.on(nEvent, func, (JCWorkerThread*)pInThread);
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kWorker.start();
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kWorker.stop();
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
m_kJS.init(nPort);
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
m_kJS.uninit();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
m_kWorker.setLoopFunc(func);
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFunction.push_back(task);
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
for (std::function<void(void)>& task : m_DbgFunction)
|
||||
{
|
||||
task();
|
||||
}
|
||||
m_DbgFunction.clear();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
bool bRet = false;
|
||||
m_DbgFuncLock.lock();
|
||||
bRet = m_DbgFunction.size() > 0;
|
||||
m_DbgFuncLock.unlock();
|
||||
return bRet;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return &m_kWorker;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
|
||||
std::mutex m_DbgFuncLock;
|
||||
JSV8Worker m_kWorker;
|
||||
Javascript m_kJS;
|
||||
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//把Javascript对象放到一个单独的线程中执行。
|
||||
class JSSingleThread : public JSThreadInterface
|
||||
{
|
||||
public:
|
||||
|
||||
JSSingleThread()
|
||||
{
|
||||
|
||||
}
|
||||
~JSSingleThread()
|
||||
{
|
||||
//uninitialize();
|
||||
}
|
||||
void post(std::function<void(void)> func)
|
||||
{
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.push_back(func);
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
void on(int nEvent, JCEventEmitter::EventHandler func, void* pInThread = 0)
|
||||
{
|
||||
switch (nEvent)
|
||||
{
|
||||
case JCWorkerThread::Event_threadStart:
|
||||
m_kStartFunc.func = func;
|
||||
m_kStartFunc.bDel = false;
|
||||
break;
|
||||
case JCWorkerThread::Event_threadStop:
|
||||
m_kStopFunc.func = func;
|
||||
m_kStopFunc.bDel = false;
|
||||
break;
|
||||
default:
|
||||
LOGE("JSSingleThread on() event type error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void start()
|
||||
{
|
||||
m_kStartFunc.func(NULL);
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
m_kStopFunc.func(NULL);
|
||||
}
|
||||
void initialize(int nPort)
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.init(nPort);
|
||||
m_kJS.initJSEngine();
|
||||
}
|
||||
void uninitialize()
|
||||
{
|
||||
clearFunc();
|
||||
m_kJS.uninit();
|
||||
m_kJS.uninitJSEngine();
|
||||
}
|
||||
void setLoopFunc(std::function<bool(void)> func)
|
||||
{
|
||||
LOGE("JSSingleThread setLoopFunc error,You can't call this function on V8 Engine");
|
||||
}
|
||||
void pushDbgFunc(std::function<void(void)> task)
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFunction.push_back(task);
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void runDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
for (std::function<void(void)>& task : m_DbgFunction)
|
||||
{
|
||||
task();
|
||||
}
|
||||
m_DbgFunction.clear();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
void waitAndRunDbgFuncs()
|
||||
{
|
||||
m_DbgFuncLock.lock();
|
||||
m_DbgFuncLock.unlock();
|
||||
}
|
||||
bool hasDbgFuncs()
|
||||
{
|
||||
bool bRet = false;
|
||||
m_DbgFuncLock.lock();
|
||||
bRet = m_DbgFunction.size() > 0;
|
||||
m_DbgFuncLock.unlock();
|
||||
return bRet;
|
||||
}
|
||||
JCWorkerThread* getWorker()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void run(Javascript::voidfun func, void* pData)
|
||||
{
|
||||
v8::TryCatch try_catch(m_kJS.m_pIsolate);
|
||||
runFunQueue();
|
||||
if (pData)func(pData);
|
||||
if (try_catch.HasCaught())
|
||||
{
|
||||
__JSRun::ReportException(m_kJS.m_pIsolate, &try_catch);
|
||||
}
|
||||
}
|
||||
void clearFunc()
|
||||
{
|
||||
m_kQueueLock.lock();
|
||||
m_vFuncQueue.clear();
|
||||
m_kQueueLock.unlock();
|
||||
}
|
||||
public:
|
||||
|
||||
void runFunQueue()
|
||||
{
|
||||
std::vector<std::function<void(void)>> vWorkQueue;
|
||||
m_kQueueLock.lock();
|
||||
std::swap(vWorkQueue, m_vFuncQueue);
|
||||
m_kQueueLock.unlock();
|
||||
for (int i = 0; i < (int)vWorkQueue.size(); i++)
|
||||
{
|
||||
vWorkQueue[i]();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<std::function<void(void)>> m_DbgFunction; //调试函数
|
||||
std::mutex m_DbgFuncLock;
|
||||
Javascript m_kJS;
|
||||
JCEventEmitter::EvtHandlerPack m_kStartFunc;
|
||||
JCEventEmitter::EvtHandlerPack m_kStopFunc;
|
||||
std::vector<std::function<void(void)>> m_vFuncQueue; //需要在此线程执行的函数的队列
|
||||
std::mutex m_kQueueLock;
|
||||
|
||||
};
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JSEnv_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,169 @@
|
||||
#ifdef JS_V8
|
||||
#include "JsBinder.h"
|
||||
#include "../JSInterface.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
namespace laya {
|
||||
|
||||
thread_local JSClassMgr JSClassMgr::__Ins;
|
||||
|
||||
void imp_js2cfunc_common(const FunctionCallbackInfo<Value>& args) {
|
||||
void* pExData = External::Cast(*args.Data())->Value();
|
||||
Local<Object> pthis = args.This();
|
||||
if (pthis->InternalFieldCount() > 1) {
|
||||
JsObjClassInfo* id = (JsObjClassInfo*)Handle<External>::Cast(pthis->GetInternalField(1))->Value();
|
||||
void *pObj = Handle<External>::Cast(pthis->GetInternalField(0))->Value();
|
||||
int a = 0;
|
||||
}
|
||||
JSP_RUN_SCRIPT("printstack();");
|
||||
throw - 1;//不能调到这里 //支持基本类型,或者Value
|
||||
}
|
||||
|
||||
bool checkJSToCArgs(const FunctionCallbackInfo<Value>& args, int num) {
|
||||
int len = args.Length();
|
||||
if (len >= num)
|
||||
return true;
|
||||
static char buff[512];
|
||||
/*算了,别alert了,log把
|
||||
sprintf(buff, "alert('arguments number err: %d:%d');printstack();", num, len);
|
||||
JSP_RUN_SCRIPT(buff);
|
||||
throw - 1;//不能调到这里 //支持基本类型,或者Value
|
||||
*/
|
||||
sprintf(buff, "console.log('arguments number err: %d:%d');var e = new Error();console.log(e.stack);", num, len);
|
||||
JSP_RUN_SCRIPT(buff);
|
||||
return false;
|
||||
}
|
||||
|
||||
Local<Function> createJSMethodRaw(FunctionCallback func, JsValue data) {
|
||||
Isolate* pIso = Isolate::GetCurrent();
|
||||
Local<FunctionTemplate> method = FunctionTemplate::New(pIso);
|
||||
method->SetCallHandler(func, data);
|
||||
return method->GetFunction();
|
||||
}
|
||||
|
||||
|
||||
JSObjBaseV8::JSObjBaseV8() {
|
||||
mpRefArray = NULL;
|
||||
mpCurJsArgs = NULL;
|
||||
mpJsThis = NULL;
|
||||
mnRefArrSize = 0;
|
||||
mbWeakThis = true;
|
||||
//放在构造里面,容易导致没有js环境而非法。还是往后放放吧。
|
||||
mpJsIso = NULL;
|
||||
//mpJsIso = Isolate::GetCurrent();
|
||||
}
|
||||
|
||||
JSObjBaseV8::~JSObjBaseV8() {
|
||||
if (!mbWeakThis) {
|
||||
mpJsThis->Reset();
|
||||
delete mpJsThis;
|
||||
mpJsThis = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void JSObjBaseV8::destroyWeakCB(const WeakCallbackInfo<Persistent<Object> >& data) {
|
||||
HandleScope __lHandleScope(Isolate::GetCurrent());
|
||||
Persistent<Object> *pPersistentVal = data.GetParameter();
|
||||
//Handle<Object> pNewIns = Local<Object>::New(Isolate::GetCurrent(), *pPersistentVal);
|
||||
//T *ptr = (T *)Handle<External>::Cast(pNewIns->GetInternalField(0))->Value();
|
||||
//delete ptr;
|
||||
pPersistentVal->Reset();
|
||||
delete pPersistentVal;
|
||||
}
|
||||
|
||||
void JSObjBaseV8::destroyWeakRefArray(const WeakCallbackInfo<Persistent<Array> >& data) {
|
||||
Persistent<Array>* pData = data.GetParameter();
|
||||
//JSObjBaseV8* pObj = pData->pObj;
|
||||
if (pData == NULL)
|
||||
return;
|
||||
//Isolate* piso = Isolate::GetCurrent();
|
||||
//HandleScope __lHandleScope(piso);
|
||||
/*
|
||||
Local<Array> refArr = pData->Get(piso);
|
||||
int sz = refArr->Length();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
refArr->Delete(piso->GetCurrentContext(), i);
|
||||
}
|
||||
*/
|
||||
pData->Reset();
|
||||
delete pData;
|
||||
}
|
||||
|
||||
void JSObjBaseV8::retainThis() {
|
||||
//我觉得这个其实应该不用。
|
||||
mRetainedThis.Reset(mpJsIso, mpJsThis->Get(mpJsIso));
|
||||
}
|
||||
|
||||
void JSObjBaseV8::releaseThis() {
|
||||
mRetainedThis.Reset();
|
||||
}
|
||||
|
||||
void JSObjBaseV8::createJSObj() {
|
||||
if (!mpJsIso)mpJsIso = Isolate::GetCurrent();
|
||||
Local<Object> jsobj = Local<Object>::New(mpJsIso, Object::New(mpJsIso));
|
||||
mpJsThis = new Persistent<Object>(mpJsIso, jsobj);
|
||||
mbWeakThis = false;
|
||||
createRefArray();
|
||||
}
|
||||
|
||||
/*
|
||||
void JSObjBaseV8::addRefHandle(JsObjHandle2* handle) {
|
||||
handle->m_pObj = this;
|
||||
handle->m_nID = mnRefArrSize++;
|
||||
}
|
||||
*/
|
||||
//創建一個數組,用於保存引用的js對象。
|
||||
void JSObjBaseV8::createRefArray() {
|
||||
mpJsIso = Isolate::GetCurrent();
|
||||
Local<Array> refarr = Array::New(mpJsIso, mnRefArrSize);
|
||||
int le = refarr->Length();
|
||||
Local<Object> jsthis = Local<Object>::New(mpJsIso, *mpJsThis);
|
||||
//需要把它加到this的引用中,防止这个数组被删除掉。
|
||||
jsthis->Set(Js_Str(mpJsIso, "__internal_refArray"), refarr);
|
||||
//这个是为了访问方便。可能去掉更好。
|
||||
mpRefArray = new Persistent<Array>(mpJsIso, refarr);
|
||||
//由于自己有引用,所以不用再在回调中删掉了。
|
||||
mpRefArray->SetWeak(mpRefArray, JSObjBaseV8::destroyWeakRefArray, v8::WeakCallbackType::kInternalFields);
|
||||
}
|
||||
|
||||
void JSObjBaseV8::setRefObj(int idx, JsValue obj) {
|
||||
if (!mpRefArray)
|
||||
return;
|
||||
if (mnRefArrSize <= idx)mnRefArrSize = idx + 1;
|
||||
Local<Array> refArr = mpRefArray->Get(mpJsIso);
|
||||
refArr->Set(idx, obj);
|
||||
}
|
||||
|
||||
Local<Object> JSObjBaseV8::getRefObj(int idx) {
|
||||
Local<Array> refArr = mpRefArray->Get(mpJsIso);
|
||||
return refArr->Get(idx).As<Object>();
|
||||
}
|
||||
|
||||
Persistent<Object>* JSObjBaseV8::weakHoldJsObj(Local<Object>& pobj) {
|
||||
Persistent<Object>* pObj = new Persistent<Object>(mpJsIso, pobj);
|
||||
pObj->SetWeak(pObj, destroyWeakCB, v8::WeakCallbackType::kInternalFields);
|
||||
return pObj;
|
||||
}
|
||||
|
||||
JsValue JSObjBaseV8::callJsFunc(JsFunction& func) {
|
||||
int argc = 0;
|
||||
Local<Value> argv[1];
|
||||
return _callJsFunc(func, argc, argv);
|
||||
}
|
||||
|
||||
bool JsObjHandle2::Empty() {
|
||||
if (!m_pObj)
|
||||
return true;
|
||||
return m_pObj->getRefObj(m_nID).IsEmpty();
|
||||
}
|
||||
|
||||
void JsObjHandle2::set(JsValue& v) {
|
||||
if (m_pObj == NULL) {
|
||||
LOGE("throw set jsvalue m_pObj==null ");
|
||||
throw - 4;
|
||||
}
|
||||
m_pObj->setRefObj(m_nID, v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user