Separate FinalizeHook for ref objects and non ref objects

This commit is contained in:
pandamicro 2016-12-19 11:50:32 +08:00
parent a73485a1bc
commit 2b6e84e9a2
7 changed files with 131 additions and 57 deletions

View File

@ -365,7 +365,7 @@ void GLView::handleTouchesMove(int num, intptr_t ids[], float xs[], float ys[],
continue; continue;
} }
CCLOGINFO("Moving touches with id: %d, x=%f, y=%f, force=%f, maxFource=%f", id, x, y, force, maxForce); CCLOGINFO("Moving touches with id: %d, x=%f, y=%f, force=%f, maxFource=%f", (int)id, x, y, force, maxForce);
Touch* touch = g_touches[iter->second]; Touch* touch = g_touches[iter->second];
if (touch) if (touch)
{ {
@ -417,7 +417,7 @@ void GLView::handleTouchesOfEndOrCancel(EventTouch::EventCode eventCode, int num
Touch* touch = g_touches[iter->second]; Touch* touch = g_touches[iter->second];
if (touch) if (touch)
{ {
CCLOGINFO("Ending touches with id: %d, x=%f, y=%f", id, x, y); CCLOGINFO("Ending touches with id: %d, x=%f, y=%f", (int)id, x, y);
touch->setTouchInfo(iter->second, (x - _viewPortRect.origin.x) / _scaleX, touch->setTouchInfo(iter->second, (x - _viewPortRect.origin.x) / _scaleX,
(y - _viewPortRect.origin.y) / _scaleY); (y - _viewPortRect.origin.y) / _scaleY);

View File

@ -1438,7 +1438,7 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
for (const auto& touch : touches) for (const auto& touch : touches)
{ {
JS::RootedValue jsret(_cx, OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, touch, typeClassTouch, "cocos2d::Touch"))); JS::RootedValue jsret(_cx, OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, touch, typeClassTouch)));
if (!JS_SetElement(_cx, jsretArr, count, jsret)) if (!JS_SetElement(_cx, jsretArr, count, jsret))
{ {
break; break;
@ -1451,7 +1451,7 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
{ {
jsval dataVal[2]; jsval dataVal[2];
dataVal[0] = OBJECT_TO_JSVAL(jsretArr); dataVal[0] = OBJECT_TO_JSVAL(jsretArr);
dataVal[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClassEvent, "cocos2d::EventTouch")); dataVal[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClassEvent));
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);
} }
@ -1459,7 +1459,6 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
{ {
removeJSObject(_cx, touch); removeJSObject(_cx, touch);
} }
removeJSObject(_cx, event); removeJSObject(_cx, event);
return ret; return ret;
@ -1485,8 +1484,8 @@ bool ScriptingCore::handleTouchEvent(void* nativeObj, cocos2d::EventTouch::Event
js_type_class_t *typeClassEvent = js_get_type_from_native<cocos2d::EventTouch>((cocos2d::EventTouch*)event); js_type_class_t *typeClassEvent = js_get_type_from_native<cocos2d::EventTouch>((cocos2d::EventTouch*)event);
jsval dataVal[2]; jsval dataVal[2];
dataVal[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, touch, typeClassTouch, "cocos2d::Touch")); dataVal[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, touch, typeClassTouch));
dataVal[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClassEvent, "cocos2d::EventTouch")); dataVal[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClassEvent));
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);
} }
@ -1514,7 +1513,7 @@ bool ScriptingCore::handleMouseEvent(void* nativeObj, cocos2d::EventMouse::Mouse
if (p) if (p)
{ {
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::EventMouse>((cocos2d::EventMouse*)event); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::EventMouse>((cocos2d::EventMouse*)event);
jsval dataVal = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClass, "cocos2d::EventMouse")); jsval dataVal = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClass));
ret = executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), funcName.c_str(), 1, &dataVal, jsvalRet); ret = executeFunctionWithOwner(OBJECT_TO_JSVAL(p->obj), funcName.c_str(), 1, &dataVal, jsvalRet);
removeJSObject(_cx, event); removeJSObject(_cx, event);
@ -1611,7 +1610,7 @@ bool ScriptingCore::handleKeyboardEvent(void* nativeObj, cocos2d::EventKeyboard:
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::EventKeyboard>((cocos2d::EventKeyboard*)event); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::EventKeyboard>((cocos2d::EventKeyboard*)event);
jsval args[2] = { jsval args[2] = {
int32_to_jsval(_cx, (int32_t)keyCode), int32_to_jsval(_cx, (int32_t)keyCode),
OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClass, "cocos2d::EventKeyboard")) OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClass))
}; };
if (isPressed) if (isPressed)
@ -1662,7 +1661,7 @@ int ScriptingCore::executeCustomTouchesEvent(EventTouch::EventCode eventType,
{ {
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch);
jsval jsret = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass, "cocos2d::Touch")); jsval jsret = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass));
JS::RootedValue jsval(_cx, jsret); JS::RootedValue jsval(_cx, jsret);
if (!JS_SetElement(this->_cx, jsretArr, count, jsval)) { if (!JS_SetElement(this->_cx, jsretArr, count, jsval)) {
break; break;
@ -1690,7 +1689,7 @@ int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType, Touc
std::string funcName = getTouchFuncName(eventType); std::string funcName = getTouchFuncName(eventType);
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch);
jsval jsTouch = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass, "cocos2d::Touch")); jsval jsTouch = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass));
executeFunctionWithOwner(OBJECT_TO_JSVAL(obj), funcName.c_str(), 1, &jsTouch, &retval); executeFunctionWithOwner(OBJECT_TO_JSVAL(obj), funcName.c_str(), 1, &jsTouch, &retval);
@ -1709,7 +1708,7 @@ int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType,
std::string funcName = getTouchFuncName(eventType); std::string funcName = getTouchFuncName(eventType);
js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch); js_type_class_t *typeClass = js_get_type_from_native<cocos2d::Touch>(touch);
jsval jsTouch = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass, "cocos2d::Touch")); jsval jsTouch = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(this->_cx, touch, typeClass));
executeFunctionWithOwner(OBJECT_TO_JSVAL(obj), funcName.c_str(), 1, &jsTouch, retval); executeFunctionWithOwner(OBJECT_TO_JSVAL(obj), funcName.c_str(), 1, &jsTouch, retval);
@ -2308,12 +2307,16 @@ JSObject* jsb_create_weak_jsobject(JSContext *cx, void *native, js_type_class_t
JS::RootedObject parent(cx, typeClass->parentProto.ref()); JS::RootedObject parent(cx, typeClass->parentProto.ref());
JS::RootedObject jsObj(cx, JS_NewObject(cx, typeClass->jsclass, proto, parent)); JS::RootedObject jsObj(cx, JS_NewObject(cx, typeClass->jsclass, proto, parent));
auto proxy = jsb_new_proxy(native, jsObj); auto proxy = jsb_new_proxy(native, jsObj);
js_add_FinalizeHook(cx, jsObj, false);
#if ! CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if ! CC_ENABLE_GC_FOR_NATIVE_OBJECTS
JS::AddNamedObjectRoot(cx, &proxy->obj, debug); JS::AddNamedObjectRoot(cx, &proxy->obj, debug);
#else #else
#if COCOS2D_DEBUG > 1 #if COCOS2D_DEBUG > 1
if (debug != nullptr)
{
CCLOG("++++++WEAK_REF++++++ Cpp(%s): %p - JS: %p", debug, native, jsObj.get()); CCLOG("++++++WEAK_REF++++++ Cpp(%s): %p - JS: %p", debug, native, jsObj.get());
}
#endif // COCOS2D_DEBUG #endif // COCOS2D_DEBUG
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS #endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
return jsObj; return jsObj;
@ -2336,7 +2339,7 @@ JSObject* jsb_ref_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_ty
js_proxy_t* newproxy = jsb_new_proxy(ref, jsObj); js_proxy_t* newproxy = jsb_new_proxy(ref, jsObj);
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
ref->retain(); ref->retain();
js_add_FinalizeHook(cx, jsObj); js_add_FinalizeHook(cx, jsObj, true);
#if COCOS2D_DEBUG > 1 #if COCOS2D_DEBUG > 1
CCLOG("++++++RETAINED++++++ Cpp(%s): %p - JS: %p", debug, ref, jsObj.get()); CCLOG("++++++RETAINED++++++ Cpp(%s): %p - JS: %p", debug, ref, jsObj.get());
#endif // COCOS2D_DEBUG #endif // COCOS2D_DEBUG
@ -2398,7 +2401,7 @@ void jsb_ref_init(JSContext* cx, JS::Heap<JSObject*> *obj, Ref* ref, const char*
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
(void)ref; (void)ref;
JS::RootedObject jsObj(cx, *obj); JS::RootedObject jsObj(cx, *obj);
js_add_FinalizeHook(cx, jsObj); js_add_FinalizeHook(cx, jsObj, true);
// don't retain it, already retained // don't retain it, already retained
#if COCOS2D_DEBUG > 1 #if COCOS2D_DEBUG > 1
CCLOG("++++++RETAINED++++++ Cpp(%s): %p - JS: %p", debug, ref, jsObj.get()); CCLOG("++++++RETAINED++++++ Cpp(%s): %p - JS: %p", debug, ref, jsObj.get());
@ -2418,7 +2421,7 @@ void jsb_ref_autoreleased_init(JSContext* cx, JS::Heap<JSObject*> *obj, Ref* ref
(void)obj; (void)obj;
ref->retain(); ref->retain();
JS::RootedObject jsObj(cx, *obj); JS::RootedObject jsObj(cx, *obj);
js_add_FinalizeHook(cx, jsObj); js_add_FinalizeHook(cx, jsObj, 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);
@ -2440,7 +2443,9 @@ void jsb_ref_rebind(JSContext* cx, JS::HandleObject jsobj, js_proxy_t *proxy, co
// Rebind js obj with new action // Rebind js obj with new action
js_proxy_t* newProxy = jsb_new_proxy(newRef, jsobj); js_proxy_t* newProxy = jsb_new_proxy(newRef, jsobj);
#if !CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
CC_UNUSED_PARAM(newProxy);
#else
JS::AddNamedObjectRoot(cx, &newProxy->obj, debug); JS::AddNamedObjectRoot(cx, &newProxy->obj, debug);
#endif #endif
} }

View File

@ -665,7 +665,7 @@ JSObject* jsb_ref_get_or_create_jsobject(JSContext *cx, cocos2d::Ref *ref, js_ty
* If it can't find it, it will create a new one associating it to Ref * If it can't find it, it will create a new one associating it to Ref
* Call this function for objects that might return an already existing copy when you create them. For example, `Animation3D::create()`; * Call this function for objects that might return an already existing copy when you create them. For example, `Animation3D::create()`;
*/ */
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=nullptr);
/** /**
* It will try to get the associated JSObjct for the native object. * It will try to get the associated JSObjct for the native object.
@ -673,7 +673,7 @@ JSObject* jsb_ref_autoreleased_get_or_create_jsobject(JSContext *cx, cocos2d::Re
* The reference created from JSObject to native object is weak because it won't retain it. * The reference created from JSObject to native object is weak because it won't retain it.
* The behavior is exactly the same with 'jsb_ref_get_or_create_jsobject' when CC_ENABLE_GC_FOR_NATIVE_OBJECTS deactivated. * The behavior is exactly the same with 'jsb_ref_get_or_create_jsobject' when CC_ENABLE_GC_FOR_NATIVE_OBJECTS deactivated.
*/ */
CC_JS_DLL JSObject* jsb_get_or_create_weak_jsobject(JSContext *cx, void *native, js_type_class_t *typeClass, const char* debug); CC_JS_DLL JSObject* jsb_get_or_create_weak_jsobject(JSContext *cx, void *native, js_type_class_t *typeClass, const char* debug=nullptr);
/** /**
* Register finalize hook and its owner as an entry in _js_hook_owner_map, * Register finalize hook and its owner as an entry in _js_hook_owner_map,

View File

@ -562,10 +562,19 @@ js_type_class_t *js_get_type_from_node(cocos2d::Node* native_obj)
return js_get_type_from_native<cocos2d::Node>(native_obj); return js_get_type_from_native<cocos2d::Node>(native_obj);
} }
void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target) void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target, bool isRef)
{ {
JS::RootedObject proto(cx, jsb_FinalizeHook_prototype); JS::RootedObject hook(cx);
JS::RootedObject hook(cx, JS_NewObject(cx, jsb_FinalizeHook_class, proto, JS::NullPtr())); if (isRef)
{
JS::RootedObject proto(cx, jsb_RefFinalizeHook_prototype);
hook = JS_NewObject(cx, jsb_RefFinalizeHook_class, proto, JS::NullPtr());
}
else
{
JS::RootedObject proto(cx, jsb_ObjFinalizeHook_prototype);
hook = JS_NewObject(cx, jsb_ObjFinalizeHook_class, proto, JS::NullPtr());
}
jsb_register_finalize_hook(hook.get(), target.get()); jsb_register_finalize_hook(hook.get(), target.get());
JS::RootedValue hookVal(cx, OBJECT_TO_JSVAL(hook)); JS::RootedValue hookVal(cx, OBJECT_TO_JSVAL(hook));
JS_SetProperty(cx, target, "__hook", hookVal); JS_SetProperty(cx, target, "__hook", hookVal);
@ -5876,15 +5885,17 @@ bool js_cocos2dx_ComponentJS_getScriptObject(JSContext *cx, uint32_t argc, jsval
return false; return false;
} }
JSClass *jsb_FinalizeHook_class; JSClass *jsb_RefFinalizeHook_class;
JSObject *jsb_FinalizeHook_prototype; JSObject *jsb_RefFinalizeHook_prototype;
JSClass *jsb_ObjFinalizeHook_class;
JSObject *jsb_ObjFinalizeHook_prototype;
static bool jsb_FinalizeHook_constructor(JSContext *cx, uint32_t argc, jsval *vp) static bool jsb_RefFinalizeHook_constructor(JSContext *cx, uint32_t argc, jsval *vp)
{ {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
// Create new object // Create new object
JS::RootedObject proto(cx, jsb_FinalizeHook_prototype); JS::RootedObject proto(cx, jsb_RefFinalizeHook_prototype);
JS::RootedObject obj(cx, JS_NewObject(cx, jsb_FinalizeHook_class, proto, JS::NullPtr())); JS::RootedObject obj(cx, JS_NewObject(cx, jsb_RefFinalizeHook_class, proto, JS::NullPtr()));
// Register arguments[0] as owner // Register arguments[0] as owner
if (!args.get(0).isNullOrUndefined()) if (!args.get(0).isNullOrUndefined())
{ {
@ -5893,7 +5904,7 @@ static bool jsb_FinalizeHook_constructor(JSContext *cx, uint32_t argc, jsval *vp
args.rval().set(OBJECT_TO_JSVAL(obj)); args.rval().set(OBJECT_TO_JSVAL(obj));
return true; return true;
} }
void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj) void jsb_RefFinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
{ {
ScriptingCore *sc = ScriptingCore::getInstance(); ScriptingCore *sc = ScriptingCore::getInstance();
JSContext *cx = sc->getGlobalContext(); JSContext *cx = sc->getGlobalContext();
@ -5902,7 +5913,7 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
if (ownerPtr) if (ownerPtr)
{ {
JS::RootedObject owner(cx, ownerPtr); JS::RootedObject owner(cx, ownerPtr);
CCLOGINFO("jsbindings: finalizing JS object via Finalizehook %p", owner.get()); CCLOGINFO("jsbindings: finalizing JS object via RefFinalizehook %p", owner.get());
js_proxy_t* nproxy = nullptr; js_proxy_t* nproxy = nullptr;
js_proxy_t* jsproxy = nullptr; js_proxy_t* jsproxy = nullptr;
jsproxy = jsb_get_js_proxy(owner); jsproxy = jsb_get_js_proxy(owner);
@ -5931,11 +5942,6 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
CCLOG("------RELEASED------ Cpp: %p - JS: %p", refObj, ownerPtr); CCLOG("------RELEASED------ Cpp: %p - JS: %p", refObj, ownerPtr);
#endif // COCOS2D_DEBUG #endif // COCOS2D_DEBUG
} }
#if COCOS2D_DEBUG > 1
else {
CCLOG("A non ref object have registered finalize hook: %p", nproxy->ptr);
}
#endif // COCOS2D_DEBUG
sc->setFinalizing(nullptr); sc->setFinalizing(nullptr);
} }
#if COCOS2D_DEBUG > 1 #if COCOS2D_DEBUG > 1
@ -5945,24 +5951,83 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
#endif // COCOS2D_DEBUG #endif // COCOS2D_DEBUG
} }
} }
static bool jsb_ObjFinalizeHook_constructor(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
// Create new object
JS::RootedObject proto(cx, jsb_ObjFinalizeHook_prototype);
JS::RootedObject obj(cx, JS_NewObject(cx, jsb_ObjFinalizeHook_class, proto, JS::NullPtr()));
// Register arguments[0] as owner
if (!args.get(0).isNullOrUndefined())
{
jsb_register_finalize_hook(obj.get(), args.get(0).toObjectOrNull());
}
args.rval().set(OBJECT_TO_JSVAL(obj));
return true;
}
void jsb_ObjFinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
{
ScriptingCore *sc = ScriptingCore::getInstance();
JSContext *cx = sc->getGlobalContext();
JS::RootedObject jsobj(cx, obj);
JSObject *ownerPtr = jsb_get_and_remove_hook_owner(obj);
if (ownerPtr)
{
JS::RootedObject owner(cx, ownerPtr);
CCLOGINFO("jsbindings: finalizing JS object via ObjFinalizehook %p", owner.get());
js_proxy_t* nproxy = nullptr;
js_proxy_t* jsproxy = nullptr;
jsproxy = jsb_get_js_proxy(owner);
if (jsproxy)
{
sc->setFinalizing(ownerPtr);
void jsb_register_FinalizeHook(JSContext *cx, JS::HandleObject global) { nproxy = jsb_get_native_proxy(jsproxy->ptr);
jsb_FinalizeHook_class = (JSClass *)calloc(1, sizeof(JSClass)); jsb_remove_proxy(nproxy, jsproxy);
jsb_FinalizeHook_class->name = "FinalizeHook"; #if COCOS2D_DEBUG > 1
jsb_FinalizeHook_class->addProperty = JS_PropertyStub; CCLOG("------WEAK_REF------ Cpp: %p - JS: %p", nproxy->ptr, ownerPtr);
jsb_FinalizeHook_class->delProperty = JS_DeletePropertyStub; #endif // COCOS2D_DEBUG
jsb_FinalizeHook_class->getProperty = JS_PropertyStub; sc->setFinalizing(nullptr);
jsb_FinalizeHook_class->setProperty = JS_StrictPropertyStub; }
jsb_FinalizeHook_class->enumerate = JS_EnumerateStub; }
jsb_FinalizeHook_class->resolve = JS_ResolveStub; }
jsb_FinalizeHook_class->convert = JS_ConvertStub;
jsb_FinalizeHook_class->finalize = jsb_FinalizeHook_finalize;
jsb_FinalizeHook_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
jsb_FinalizeHook_prototype = JS_InitClass(cx, global, void jsb_register_RefFinalizeHook(JSContext *cx, JS::HandleObject global) {
jsb_RefFinalizeHook_class = (JSClass *)calloc(1, sizeof(JSClass));
jsb_RefFinalizeHook_class->name = "RefFinalizeHook";
jsb_RefFinalizeHook_class->addProperty = JS_PropertyStub;
jsb_RefFinalizeHook_class->delProperty = JS_DeletePropertyStub;
jsb_RefFinalizeHook_class->getProperty = JS_PropertyStub;
jsb_RefFinalizeHook_class->setProperty = JS_StrictPropertyStub;
jsb_RefFinalizeHook_class->enumerate = JS_EnumerateStub;
jsb_RefFinalizeHook_class->resolve = JS_ResolveStub;
jsb_RefFinalizeHook_class->convert = JS_ConvertStub;
jsb_RefFinalizeHook_class->finalize = jsb_RefFinalizeHook_finalize;
jsb_RefFinalizeHook_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
jsb_RefFinalizeHook_prototype = JS_InitClass(cx, global,
JS::NullPtr(), // parent proto JS::NullPtr(), // parent proto
jsb_FinalizeHook_class, jsb_RefFinalizeHook_class,
jsb_FinalizeHook_constructor, 0, // constructor jsb_RefFinalizeHook_constructor, 0, // constructor
NULL, NULL, NULL, NULL);
}
void jsb_register_ObjFinalizeHook(JSContext *cx, JS::HandleObject global) {
jsb_ObjFinalizeHook_class = (JSClass *)calloc(1, sizeof(JSClass));
jsb_ObjFinalizeHook_class->name = "ObjFinalizeHook";
jsb_ObjFinalizeHook_class->addProperty = JS_PropertyStub;
jsb_ObjFinalizeHook_class->delProperty = JS_DeletePropertyStub;
jsb_ObjFinalizeHook_class->getProperty = JS_PropertyStub;
jsb_ObjFinalizeHook_class->setProperty = JS_StrictPropertyStub;
jsb_ObjFinalizeHook_class->enumerate = JS_EnumerateStub;
jsb_ObjFinalizeHook_class->resolve = JS_ResolveStub;
jsb_ObjFinalizeHook_class->convert = JS_ConvertStub;
jsb_ObjFinalizeHook_class->finalize = jsb_ObjFinalizeHook_finalize;
jsb_ObjFinalizeHook_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
jsb_ObjFinalizeHook_prototype = JS_InitClass(cx, global,
JS::NullPtr(), // parent proto
jsb_ObjFinalizeHook_class,
jsb_ObjFinalizeHook_constructor, 0, // constructor
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
} }
@ -5976,7 +6041,8 @@ void register_cocos2dx_js_core(JSContext* cx, JS::HandleObject global)
get_or_create_js_obj(cx, global, "jsb", &jsbObj); get_or_create_js_obj(cx, global, "jsb", &jsbObj);
// Memory management related // Memory management related
jsb_register_FinalizeHook(cx, jsbObj); jsb_register_RefFinalizeHook(cx, jsbObj);
jsb_register_ObjFinalizeHook(cx, jsbObj);
js_register_cocos2dx_PolygonInfo(cx, jsbObj); js_register_cocos2dx_PolygonInfo(cx, jsbObj);
js_register_cocos2dx_AutoPolygon(cx, jsbObj); js_register_cocos2dx_AutoPolygon(cx, jsbObj);

View File

@ -79,8 +79,10 @@ extern schedFunc_proxy_t *_schedFunc_target_ht;
extern schedTarget_proxy_t *_schedObj_target_ht; extern schedTarget_proxy_t *_schedObj_target_ht;
extern callfuncTarget_proxy_t *_callfuncTarget_native_ht; extern callfuncTarget_proxy_t *_callfuncTarget_native_ht;
extern JSClass *jsb_FinalizeHook_class; extern JSClass *jsb_RefFinalizeHook_class;
extern JSObject *jsb_FinalizeHook_prototype; extern JSObject *jsb_RefFinalizeHook_prototype;
extern JSClass *jsb_ObjFinalizeHook_class;
extern JSObject *jsb_ObjFinalizeHook_prototype;
/** /**
* You don't need to manage the returned pointer. They live for the whole life of * You don't need to manage the returned pointer. They live for the whole life of
@ -142,7 +144,7 @@ JSObject* js_get_or_create_jsobject(JSContext *cx, typename std::enable_if<std::
* In the finalize function, it mainly remove native/js proxys, release/delete the native object. * In the finalize function, it mainly remove native/js proxys, release/delete the native object.
* IMPORTANT: For Ref objects, please remember to retain the native object to correctly manage its reference count. * IMPORTANT: For Ref objects, please remember to retain the native object to correctly manage its reference count.
*/ */
void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target); void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target, bool isRef=true);
void js_add_object_reference(JS::HandleValue owner, JS::HandleValue target); void js_add_object_reference(JS::HandleValue owner, JS::HandleValue target);
void js_remove_object_reference(JS::HandleValue owner, JS::HandleValue target); void js_remove_object_reference(JS::HandleValue owner, JS::HandleValue target);
@ -170,6 +172,7 @@ protected:
JS::Heap<JS::Value> _jsCallback; JS::Heap<JS::Value> _jsCallback;
JS::Heap<JS::Value> _jsThisObj; JS::Heap<JS::Value> _jsThisObj;
JS::Heap<JS::Value> _extraData; JS::Heap<JS::Value> _extraData;
bool _rooted;
}; };

View File

@ -179,7 +179,7 @@ bool js_EventListenerAcceleration_create(JSContext *cx, uint32_t argc, jsval *vp
largv[0] = ccacceleration_to_jsval(cx, *acc); largv[0] = ccacceleration_to_jsval(cx, *acc);
if (event) { if (event) {
js_type_class_t *typeClassEvent = js_get_type_from_native<Event>(event); js_type_class_t *typeClassEvent = js_get_type_from_native<Event>(event);
largv[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent, "cocos2d::EventAcceleration")); largv[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent));
} else { } else {
largv[1] = JSVAL_NULL; largv[1] = JSVAL_NULL;
}; };
@ -246,7 +246,7 @@ bool js_EventListenerCustom_create(JSContext *cx, uint32_t argc, jsval *vp)
jsval largv[1]; jsval largv[1];
if (event) { if (event) {
js_type_class_t *typeClassEvent = js_get_type_from_native<EventCustom>(event); js_type_class_t *typeClassEvent = js_get_type_from_native<EventCustom>(event);
largv[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent, "cocos2d::EventCustom")); largv[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent));
} else { } else {
largv[0] = JSVAL_NULL; largv[0] = JSVAL_NULL;
}; };
@ -298,7 +298,7 @@ bool js_EventDispatcher_addCustomEventListener(JSContext *cx, uint32_t argc, jsv
jsval largv[1]; jsval largv[1];
if (event) { if (event) {
js_type_class_t *typeClassEvent = js_get_type_from_native<EventCustom>(event); js_type_class_t *typeClassEvent = js_get_type_from_native<EventCustom>(event);
largv[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent, "cocos2d::EventCustom")); largv[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(cx, event, typeClassEvent));
} else { } else {
largv[0] = JSVAL_NULL; largv[0] = JSVAL_NULL;
}; };

View File

@ -400,7 +400,7 @@ JS_BINDED_CONSTRUCTOR_IMPL(MinXmlHttpRequest)
js_proxy_t *p = jsb_new_proxy(req, obj); js_proxy_t *p = jsb_new_proxy(req, obj);
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS #if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
js_add_FinalizeHook(cx, obj); js_add_FinalizeHook(cx, obj, true);
// don't retain it, already retained // don't retain it, already retained
#if COCOS2D_DEBUG > 1 #if COCOS2D_DEBUG > 1
CCLOG("++++++RETAINED++++++ Cpp(XMLHttpRequest): %p - JS: %p", req, obj.get()); CCLOG("++++++RETAINED++++++ Cpp(XMLHttpRequest): %p - JS: %p", req, obj.get());