ccvector_to / ccmap_to converted to new API

and more fixes
This commit is contained in:
Ricardo Quesada 2015-12-15 12:27:53 -08:00
parent 4c8fdc760d
commit 43a573f4fd
9 changed files with 91 additions and 113 deletions

View File

@ -65,7 +65,7 @@ Ref::Ref()
Ref::~Ref() Ref::~Ref()
{ {
#if CC_ENABLE_SCRIPT_BINDING #if CC_ENABLE_SCRIPT_BINDING && not CC_ENABLE_GC_FOR_NATIVE_OBJECTS
// if the object is referenced by Lua engine, remove it // if the object is referenced by Lua engine, remove it
if (_luaID) if (_luaID)
{ {
@ -100,11 +100,7 @@ void Ref::retain()
if (scriptMgr && scriptMgr->getScriptType() == kScriptTypeJavascript) if (scriptMgr && scriptMgr->getScriptType() == kScriptTypeJavascript)
{ {
_referenceCountAtRootTime = _referenceCount-1; _referenceCountAtRootTime = _referenceCount-1;
CCLOG("retain + root: %p (%s) rc=%d rcrt=%d", this, typeid(*this).name(), _referenceCount, _referenceCountAtRootTime);
scriptMgr->rootObject(this); scriptMgr->rootObject(this);
_rooted = true;
} }
} }
#endif // CC_ENABLE_SCRIPT_BINDING #endif // CC_ENABLE_SCRIPT_BINDING
@ -116,13 +112,12 @@ void Ref::release()
--_referenceCount; --_referenceCount;
#if CC_ENABLE_SCRIPT_BINDING && CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_SCRIPT_BINDING && CC_ENABLE_GC_FOR_NATIVE_OBJECTS
if (_scriptOwned && _rooted && _referenceCount==_referenceCountAtRootTime) if (_scriptOwned && _rooted && _referenceCount==/*_referenceCountAtRootTime*/ 1)
{ {
auto scriptMgr = ScriptEngineManager::getInstance()->getScriptEngine(); auto scriptMgr = ScriptEngineManager::getInstance()->getScriptEngine();
if (scriptMgr && scriptMgr->getScriptType() == kScriptTypeJavascript) if (scriptMgr && scriptMgr->getScriptType() == kScriptTypeJavascript)
{ {
scriptMgr->unrootObject(this); scriptMgr->unrootObject(this);
_rooted = false;
} }
} }
#endif // CC_ENABLE_SCRIPT_BINDING #endif // CC_ENABLE_SCRIPT_BINDING

View File

@ -212,18 +212,30 @@ static std::string getMouseFuncName(EventMouse::MouseEventType eventType)
return funcName; return funcName;
} }
void removeJSObject(JSContext* cx, void* nativeObj) static void removeJSObject(JSContext* cx, cocos2d::Ref* nativeObj)
{ {
js_proxy_t* nproxy; js_proxy_t* nproxy;
js_proxy_t* jsproxy; js_proxy_t* jsproxy;
nproxy = jsb_get_native_proxy(nativeObj); nproxy = jsb_get_native_proxy(nativeObj);
if (nproxy) { if (nproxy)
JS::RootedObject jsobj(cx, nproxy->obj); {
jsproxy = jsb_get_js_proxy(jsobj); jsproxy = jsb_get_js_proxy(nproxy->obj);
RemoveObjectRoot(cx, &jsproxy->obj); JS::RemoveObjectRoot(cx, &jsproxy->obj);
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
nativeObj->_rooted = false;
// FIXME BUG TODO: remove this line... but if I do so
// another misterious bug appears
jsb_remove_proxy(nproxy, jsproxy); jsb_remove_proxy(nproxy, jsproxy);
#else
// only remove when not using GC,
// otherwise finalize won't be able to find the proxy
jsb_remove_proxy(nproxy, jsproxy);
#endif
} }
else CCLOG("removeJSObject: BUG: cannot find native object = %p", nativeObj);
} }
void ScriptingCore::executeJSFunctionWithThisObj(JS::HandleValue thisObj, JS::HandleValue callback) void ScriptingCore::executeJSFunctionWithThisObj(JS::HandleValue thisObj, JS::HandleValue callback)
@ -874,15 +886,16 @@ void ScriptingCore::removeScriptObjectByObject(Ref* pObj)
nproxy = jsb_get_native_proxy(ptr); nproxy = jsb_get_native_proxy(ptr);
if (nproxy) if (nproxy)
{ {
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext(); JSContext *cx = getGlobalContext();
JS::RootedObject jsobj(cx, nproxy->obj); jsproxy = jsb_get_js_proxy(nproxy->obj);
jsproxy = jsb_get_js_proxy(jsobj);
if (jsproxy) if (jsproxy)
{ {
RemoveObjectRoot(cx, &jsproxy->obj); RemoveObjectRoot(cx, &jsproxy->obj);
jsb_remove_proxy(nproxy, jsproxy); jsb_remove_proxy(nproxy, jsproxy);
} }
else CCLOG("removeScriptObjectByObject. BUG: jsproxy not found = %p", nproxy);
} }
else CCLOG("removeScriptObjectByObject. BUG: nproxy not found = %p", nproxy);
} }
@ -1185,7 +1198,6 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
JS::RootedObject jsretArr(_cx, JS_NewArrayObject(this->_cx, 0)); JS::RootedObject jsretArr(_cx, JS_NewArrayObject(this->_cx, 0));
// AddNamedObjectRoot(this->_cx, &jsretArr, "touchArray");
int count = 0; int count = 0;
js_type_class_t *typeClassEvent = nullptr; js_type_class_t *typeClassEvent = nullptr;
@ -1214,8 +1226,6 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
ret = executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), funcName.c_str(), 2, dataVal, jsvalRet); ret = executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), funcName.c_str(), 2, dataVal, jsvalRet);
} }
// JS_RemoveObjectRoot(this->_cx, &jsretArr);
for (auto& touch : touches) for (auto& touch : touches)
{ {
removeJSObject(this->_cx, touch); removeJSObject(this->_cx, touch);
@ -1570,11 +1580,9 @@ void ScriptingCore::rootObject(Ref* ref)
JSContext *cx = getGlobalContext(); JSContext *cx = getGlobalContext();
jsproxy = jsb_get_js_proxy(nproxy->obj); jsproxy = jsb_get_js_proxy(nproxy->obj);
JS::AddNamedObjectRoot(cx, &jsproxy->obj, typeid(*ref).name()); JS::AddNamedObjectRoot(cx, &jsproxy->obj, typeid(*ref).name());
ref->_rooted = true;
} }
else else CCLOG("rootObject: BUG. native not found: %p", ref);
{
CCLOG("BUG in rootObject");
}
} }
void ScriptingCore::unrootObject(Ref* ref) void ScriptingCore::unrootObject(Ref* ref)
@ -1588,11 +1596,9 @@ void ScriptingCore::unrootObject(Ref* ref)
JSContext *cx = getGlobalContext(); JSContext *cx = getGlobalContext();
jsproxy = jsb_get_js_proxy(nproxy->obj); jsproxy = jsb_get_js_proxy(nproxy->obj);
JS::RemoveObjectRoot(cx, &jsproxy->obj); JS::RemoveObjectRoot(cx, &jsproxy->obj);
ref->_rooted = false;
} }
else else CCLOG("unrootObject: BUG. native not found: %p", ref);
{
CCLOG("BUG in unrootObject");
}
} }
#pragma mark - Debug #pragma mark - Debug
@ -1922,44 +1928,59 @@ js_proxy_t* jsb_new_proxy(void* nativeObj, JS::HandleObject jsObj)
{ {
js_proxy_t* p = nullptr; js_proxy_t* p = nullptr;
JSObject* ptr = jsObj.get(); JSObject* ptr = jsObj.get();
do {
p = (js_proxy_t *)malloc(sizeof(js_proxy_t)); // native to JS index
assert(p); p = (js_proxy_t *)malloc(sizeof(js_proxy_t));
js_proxy_t* nativeObjJsObjtmp = NULL; assert(p);
HASH_FIND_PTR(_native_js_global_ht, &nativeObj, nativeObjJsObjtmp); js_proxy_t* nativeObjJsObjtmp = NULL;
assert(!nativeObjJsObjtmp); HASH_FIND_PTR(_native_js_global_ht, &nativeObj, nativeObjJsObjtmp);
p->ptr = nativeObj; assert(!nativeObjJsObjtmp);
p->obj = ptr; p->ptr = nativeObj;
HASH_ADD_PTR(_native_js_global_ht, ptr, p); p->obj = ptr;
p = (js_proxy_t *)malloc(sizeof(js_proxy_t)); HASH_ADD_PTR(_native_js_global_ht, ptr, p);
assert(p);
nativeObjJsObjtmp = NULL; // JS to native Index
HASH_FIND_PTR(_js_native_global_ht, &ptr, nativeObjJsObjtmp); p = (js_proxy_t *)malloc(sizeof(js_proxy_t));
assert(!nativeObjJsObjtmp); assert(p);
p->ptr = nativeObj; nativeObjJsObjtmp = NULL;
p->obj = ptr; HASH_FIND_PTR(_js_native_global_ht, &ptr, nativeObjJsObjtmp);
HASH_ADD_PTR(_js_native_global_ht, obj, p); assert(!nativeObjJsObjtmp);
} while(0); p->ptr = nativeObj;
p->obj = ptr;
HASH_ADD_PTR(_js_native_global_ht, obj, p);
return p; return p;
} }
js_proxy_t* jsb_get_native_proxy(void* nativeObj) js_proxy_t* jsb_get_native_proxy(void* nativeObj)
{ {
js_proxy_t* p = nullptr; js_proxy_t* p = nullptr;
JS_GET_PROXY(p, nativeObj); HASH_FIND_PTR(_native_js_global_ht, &nativeObj, p);
return p; return p;
} }
js_proxy_t* jsb_get_js_proxy(JSObject* jsObj) js_proxy_t* jsb_get_js_proxy(JSObject* jsObj)
{ {
js_proxy_t* p = nullptr; js_proxy_t* p = nullptr;
JS_GET_NATIVE_PROXY(p, jsObj); HASH_FIND_PTR(_js_native_global_ht, &jsObj, p);
return p; return p;
} }
void jsb_remove_proxy(js_proxy_t* nativeProxy, js_proxy_t* jsProxy) void jsb_remove_proxy(js_proxy_t* nativeProxy, js_proxy_t* jsProxy)
{ {
JS_REMOVE_PROXY(nativeProxy, jsProxy); if (nativeProxy)
{
HASH_DEL(_native_js_global_ht, nativeProxy);
free(nativeProxy);
}
else CCLOG("jsb_remove_proxy: BUG: nativeProxy is null");
if (jsProxy)
{
HASH_DEL(_js_native_global_ht, jsProxy);
free(jsProxy);
}
else CCLOG("jsb_remove_proxy: BUG: jsProxy is null");
} }
// //
@ -2001,7 +2022,10 @@ JSObject* jsb_ref_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_ty
js_proxy_t* newproxy = jsb_new_proxy(ref, js_obj); js_proxy_t* newproxy = jsb_new_proxy(ref, js_obj);
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
CC_UNUSED_PARAM(newproxy); CC_UNUSED_PARAM(newproxy);
// don't retain it.
// retain first copy, and before "owning" to prevent it
// from calling "rootObject"
ref->retain();
ref->_scriptOwned = true; ref->_scriptOwned = true;
#else #else
// don't autorelease it // don't autorelease it
@ -2029,7 +2053,7 @@ void jsb_ref_init(JSContext* cx, JS::Heap<JSObject*> *obj, Ref* ref, const char*
(void)cx; (void)cx;
(void)obj; (void)obj;
ref->_scriptOwned = true; ref->_scriptOwned = true;
// don't retain it. // don't retain it, already retained
#else #else
// autorelease it // autorelease it
ref->autorelease(); ref->autorelease();
@ -2043,9 +2067,10 @@ void jsb_ref_autoreleased_init(JSContext* cx, JS::Heap<JSObject*> *obj, Ref* ref
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
(void)cx; (void)cx;
(void)obj; (void)obj;
ref->_scriptOwned = true; // retain first copy, and before "owning" to prevent it
// retain it, since the object is autoreleased // from calling "rootObject"
ref->retain(); ref->retain();
ref->_scriptOwned = true;
#else #else
// don't autorelease it, since it is already autoreleased // don't autorelease it, since it is already autoreleased
JS::AddNamedObjectRoot(cx, obj, debug); JS::AddNamedObjectRoot(cx, obj, debug);
@ -2059,8 +2084,7 @@ void jsb_ref_finalize(JSFreeOp* fop, JSObject* obj)
js_proxy_t* nproxy; js_proxy_t* nproxy;
js_proxy_t* jsproxy; js_proxy_t* jsproxy;
JS::RootedObject jsobj(fop->runtime(), obj); jsproxy = jsb_get_js_proxy(obj);
jsproxy = jsb_get_js_proxy(jsobj);
if (jsproxy) if (jsproxy)
{ {
auto ref = static_cast<cocos2d::Ref*>(jsproxy->ptr); auto ref = static_cast<cocos2d::Ref*>(jsproxy->ptr);
@ -2074,6 +2098,7 @@ void jsb_ref_finalize(JSFreeOp* fop, JSObject* obj)
else else
jsb_remove_proxy(nullptr, jsproxy); jsb_remove_proxy(nullptr, jsproxy);
} }
else CCLOG("jsb_ref_finalize: BUG: proxy not found for %p", obj);
#else #else
// CCLOG("jsb_ref_finalize: JSObject address = %p", obj); // CCLOG("jsb_ref_finalize: JSObject address = %p", obj);
#endif #endif

View File

@ -618,7 +618,4 @@ JSObject* jsb_ref_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_ty
*/ */
JSObject* jsb_ref_autoreleased_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_type_class_t *typeClass, const char* debug); JSObject* jsb_ref_autoreleased_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_type_class_t *typeClass, const char* debug);
void removeJSObject(JSContext* cx, void* nativeObj);
#endif /* __SCRIPTING_CORE_H__ */ #endif /* __SCRIPTING_CORE_H__ */

View File

@ -87,8 +87,7 @@ inline js_type_class_t *js_get_type_from_native(T* native_obj) {
*/ */
template<class T> template<class T>
inline js_proxy_t *js_get_or_create_proxy(JSContext *cx, T *native_obj) { inline js_proxy_t *js_get_or_create_proxy(JSContext *cx, T *native_obj) {
js_proxy_t *proxy; js_proxy_t *proxy = jsb_get_native_proxy(native_obj);
HASH_FIND_PTR(_native_js_global_ht, &native_obj, proxy);
if (!proxy) { if (!proxy) {
js_type_class_t *typeProxy = js_get_type_from_native<T>(native_obj); js_type_class_t *typeProxy = js_get_type_from_native<T>(native_obj);
// Return NULL if can't find its type rather than making an assert. // Return NULL if can't find its type rather than making an assert.

View File

@ -557,8 +557,7 @@ public:
virtual void onEvent(Ref *controlButton, Control::EventType event) virtual void onEvent(Ref *controlButton, Control::EventType event)
{ {
js_proxy_t * p; js_proxy_t* p = jsb_get_native_proxy(controlButton);
JS_GET_PROXY(p, controlButton);
if (!p) if (!p)
{ {
log("Failed to get proxy for control button"); log("Failed to get proxy for control button");

View File

@ -35,12 +35,10 @@ void GLNode::onDraw(Mat4 &transform, uint32_t flags)
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext(); JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::GLNode>(this); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::GLNode>(this);
auto j = jsb_ref_get_or_create_jsobject(cx, this, typeClass, "cocos2d::GLNode"); JS::RootedObject jsObj(cx, jsb_ref_get_or_create_jsobject(cx, this, typeClass, "cocos2d::GLNode"));
if (j) if (jsObj.get())
{ {
JS::RootedObject jsObj(cx, j);
bool found = false; bool found = false;
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET

View File

@ -280,9 +280,11 @@ jsval meshVertexAttrib_to_jsval(JSContext* cx, const cocos2d::MeshVertexAttrib&
jsval uniform_to_jsval(JSContext* cx, const cocos2d::Uniform* uniform); jsval uniform_to_jsval(JSContext* cx, const cocos2d::Uniform* uniform);
jsval resourcedata_to_jsval(JSContext* cx, const cocos2d::ResourceData& v); jsval resourcedata_to_jsval(JSContext* cx, const cocos2d::ResourceData& v);
template<class T>
js_proxy_t *js_get_or_create_proxy(JSContext *cx, T *native_obj);
// forward declaration
template <class T> js_type_class_t *js_get_type_from_native(T* native_obj);
// Ref version of ccvector_to_jsval
template <class T> template <class T>
jsval ccvector_to_jsval(JSContext* cx, const cocos2d::Vector<T>& v) jsval ccvector_to_jsval(JSContext* cx, const cocos2d::Vector<T>& v)
{ {
@ -294,9 +296,10 @@ jsval ccvector_to_jsval(JSContext* cx, const cocos2d::Vector<T>& v)
JS::RootedValue arrElement(cx); JS::RootedValue arrElement(cx);
//First, check whether object is associated with js object. //First, check whether object is associated with js object.
js_proxy_t* jsproxy = js_get_or_create_proxy(cx, obj); js_type_class_t *typeClass = js_get_type_from_native(obj);
if (jsproxy) { JS::RootedObject jsobject(cx, jsb_ref_get_or_create_jsobject(cx, obj, typeClass, typeid(*obj).name()));
arrElement = OBJECT_TO_JSVAL(jsproxy->obj); if (jsobject.get()) {
arrElement = OBJECT_TO_JSVAL(jsobject);
} }
if (!JS_SetElement(cx, jsretArr, i, arrElement)) { if (!JS_SetElement(cx, jsretArr, i, arrElement)) {
@ -322,9 +325,11 @@ jsval ccmap_string_key_to_jsval(JSContext* cx, const cocos2d::Map<std::string, T
T obj = iter->second; T obj = iter->second;
//First, check whether object is associated with js object. //First, check whether object is associated with js object.
js_proxy_t* jsproxy = js_get_or_create_proxy(cx, obj); js_type_class_t *typeClass = js_get_type_from_native(obj);
if (jsproxy) { JS::RootedObject jsobject(cx, jsb_ref_get_or_create_jsobject(cx, obj, typeClass, typeid(*obj).name()));
element = OBJECT_TO_JSVAL(jsproxy->obj);
if (jsobject.get()) {
element = OBJECT_TO_JSVAL(jsobject);
} }
if (!key.empty()) if (!key.empty())

View File

@ -164,8 +164,7 @@ bool js_cocos2dx_SocketIO_connect(JSContext* cx, uint32_t argc, jsval* vp)
if (ret) if (ret)
{ {
// link the native object with the javascript object // link the native object with the javascript object
js_proxy_t *p; js_proxy_t *p = jsb_get_native_proxy(ret);
HASH_FIND_PTR(_native_js_global_ht, &ret, p);
if(!p) if(!p)
{ {
//previous connection not found, create a new one //previous connection not found, create a new one

View File

@ -35,9 +35,6 @@ typedef struct js_proxy {
UT_hash_handle hh; UT_hash_handle hh;
} js_proxy_t; } js_proxy_t;
extern js_proxy_t *_native_js_global_ht;
extern js_proxy_t *_js_native_global_ht;
typedef struct js_type_class { typedef struct js_type_class {
JSClass *jsclass; JSClass *jsclass;
mozilla::Maybe<JS::PersistentRootedObject> proto; mozilla::Maybe<JS::PersistentRootedObject> proto;
@ -60,42 +57,6 @@ public:
}; };
#define JS_NEW_PROXY(p, native_obj, js_obj) \
do { \
p = (js_proxy_t *)malloc(sizeof(js_proxy_t)); \
assert(p); \
js_proxy_t* native_obj##js_obj##tmp = NULL; \
HASH_FIND_PTR(_native_js_global_ht, &native_obj, native_obj##js_obj##tmp); \
assert(!native_obj##js_obj##tmp); \
p->ptr = native_obj; \
p->obj = js_obj; \
HASH_ADD_PTR(_native_js_global_ht, ptr, p); \
p = (js_proxy_t *)malloc(sizeof(js_proxy_t)); \
assert(p); \
native_obj##js_obj##tmp = NULL; \
HASH_FIND_PTR(_js_native_global_ht, &js_obj, native_obj##js_obj##tmp); \
assert(!native_obj##js_obj##tmp); \
p->ptr = native_obj; \
p->obj = js_obj; \
HASH_ADD_PTR(_js_native_global_ht, obj, p); \
} while(0) \
#define JS_GET_PROXY(p, native_obj) \
do { \
HASH_FIND_PTR(_native_js_global_ht, &native_obj, p); \
} while (0)
#define JS_GET_NATIVE_PROXY(p, js_obj) \
do { \
HASH_FIND_PTR(_js_native_global_ht, &js_obj, p); \
} while (0)
#define JS_REMOVE_PROXY(nproxy, jsproxy) \
do { \
if (nproxy) { HASH_DEL(_native_js_global_ht, nproxy); free(nproxy); } \
if (jsproxy) { HASH_DEL(_js_native_global_ht, jsproxy); free(jsproxy); } \
} while (0)
#define TEST_NATIVE_OBJECT(cx, native_obj) \ #define TEST_NATIVE_OBJECT(cx, native_obj) \
if (!native_obj) { \ if (!native_obj) { \
JS_ReportError(cx, "Invalid Native Object"); \ JS_ReportError(cx, "Invalid Native Object"); \