#ifndef _JSC_BINDER_H__ #define _JSC_BINDER_H__ #include #include "JSCProxyTransfer.h" #include "JSCProxyType.h" #include "JSCProxyClass.h" #include 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 allCls; void resetAllRegClass(){ for( int i=0,sz=allCls.size(); iaddFunction( #name, func ); #define JSP_ADD_GLOBAL_PROPERTY(name, v) \ JSCGlobal::getInstance()->addProperty( #name, v ); #define JSP_CLASS(name, cls) \ JSCClass* pJSCClass = JSCClass::getInstance(); #define JSP_GLOBAL_CLASS(name, cls) \ JSCClass* pJSCClass = JSCClass::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()); #define JSP_INSTALL_CLASS(name,cls) \ pJSCClass->finish(name); \ JSClassMgr::GetThreadInstance()->allCls.push_back(JSCClass::reset); #define JSP_INSTALL_GLOBAL_CLASS(name,cls,inst) \ pJSCClass->finishToGlobal(name,inst); \ JSClassMgr::GetThreadInstance()->allCls.push_back(JSCClass::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 JSValueRef callJsFunc(JSValueRef func, P1 p1) { int argc = 1; JSValueRef argv[1]; argv[0] = __TransferToJs::ToJs(p1); return _callJsFunc(func, argc, argv); } template JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2) { int argc = 2; JSValueRef argv[2]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); return _callJsFunc(func, argc, argv); } template JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3) { int argc = 3; JSValueRef argv[3]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); return _callJsFunc(func, argc, argv); } template JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4) { int argc = 4; JSValueRef argv[4]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); return _callJsFunc(func, argc, argv); } template JSValueRef callJsFunc(JSValueRef func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { int argc = 5; JSValueRef argv[5]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); return _callJsFunc(func, argc, argv); } template 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::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); return _callJsFunc(func, argc, argv); } template 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::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); return _callJsFunc(func, argc, argv); } template 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::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); argv[7] = __TransferToJs::ToJs(p8); return _callJsFunc(func, argc, argv); } template 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::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); argv[7] = __TransferToJs::ToJs(p8); argv[8] = __TransferToJs::ToJs(p9); argv[9] = __TransferToJs::ToJs(p10); argv[10] = __TransferToJs::ToJs(p11); argv[11] = __TransferToJs::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 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 bool IsTypeof() { return IsTypeof<_Tp>(m_pValue); } template 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 bool Call(P1 p1) { CALLJSPRE m_pReturn = m_pObj->callJsFunc(func,p1); return true; } template bool Call(P1 p1, P2 p2) { CALLJSPRE m_pReturn = m_pObj->callJsFunc(func, p1, p2); return true; } template bool Call(P1 p1, P2 p2, P3 p3) { CALLJSPRE m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4) { CALLJSPRE m_pReturn = m_pObj->callJsFunc(func, p1, p2, p3, p4); return true; } template 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 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 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