Merge pull request #2766 from dumganhar/jsb-delegate-crash-develop

fixed #2143: cc.ScrollView(TableView, EditBox).setDelegate(tmp object) causes crash.
This commit is contained in:
James Chen 2013-06-04 23:58:56 -07:00
commit 7c2ce0da64
4 changed files with 166 additions and 9 deletions

View File

@ -107,6 +107,11 @@ void CCEditBox::setDelegate(CCEditBoxDelegate* pDelegate)
} }
} }
CCEditBoxDelegate* CCEditBox::getDelegate()
{
return m_pDelegate;
}
void CCEditBox::setText(const char* pText) void CCEditBox::setText(const char* pText)
{ {
if (pText != NULL) if (pText != NULL)

View File

@ -196,9 +196,10 @@ public:
bool initWithSizeAndBackgroundSprite(const CCSize& size, CCScale9Sprite* pNormal9SpriteBg); bool initWithSizeAndBackgroundSprite(const CCSize& size, CCScale9Sprite* pNormal9SpriteBg);
/** /**
* Set the delegate for edit box. * Gets/Sets the delegate for edit box.
*/ */
void setDelegate(CCEditBoxDelegate* pDelegate); void setDelegate(CCEditBoxDelegate* pDelegate);
CCEditBoxDelegate* getDelegate();
/** /**
* Registers a script function that will be called for EditBox events. * Registers a script function that will be called for EditBox events.
* *

View File

@ -13,9 +13,25 @@
USING_NS_CC; USING_NS_CC;
USING_NS_CC_EXT; USING_NS_CC_EXT;
class JSB_ScrollViewDelegate : public CCScrollViewDelegate class JSB_ScrollViewDelegate
: public CCNode
, public CCScrollViewDelegate
{ {
public: public:
JSB_ScrollViewDelegate()
: m_pJSDelegate(NULL)
, m_bNeedUnroot(false)
{}
virtual ~JSB_ScrollViewDelegate()
{
if (m_bNeedUnroot)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_RemoveObjectRoot(cx, &m_pJSDelegate);
}
}
virtual void scrollViewDidScroll(CCScrollView* view) virtual void scrollViewDidScroll(CCScrollView* view)
{ {
js_proxy_t * p = jsb_get_native_proxy(view); js_proxy_t * p = jsb_get_native_proxy(view);
@ -37,9 +53,19 @@ public:
void setJSDelegate(JSObject* pJSDelegate) void setJSDelegate(JSObject* pJSDelegate)
{ {
m_pJSDelegate = pJSDelegate; m_pJSDelegate = pJSDelegate;
// Check whether the js delegate is a pure js object.
js_proxy_t* p = jsb_get_js_proxy(m_pJSDelegate);
if (!p)
{
m_bNeedUnroot = true;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_AddNamedObjectRoot(cx, &m_pJSDelegate, "TableViewDelegate");
}
} }
private: private:
JSObject* m_pJSDelegate; JSObject* m_pJSDelegate;
bool m_bNeedUnroot;
}; };
static JSBool js_cocos2dx_CCScrollView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp) static JSBool js_cocos2dx_CCScrollView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)
@ -55,8 +81,17 @@ static JSBool js_cocos2dx_CCScrollView_setDelegate(JSContext *cx, uint32_t argc,
JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]); JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]);
JSB_ScrollViewDelegate* nativeDelegate = new JSB_ScrollViewDelegate(); JSB_ScrollViewDelegate* nativeDelegate = new JSB_ScrollViewDelegate();
nativeDelegate->setJSDelegate(jsDelegate); nativeDelegate->setJSDelegate(jsDelegate);
JSB_ScrollViewDelegate* oldDelegate = (JSB_ScrollViewDelegate*)cobj->getDelegate();
if (oldDelegate)
{
oldDelegate->removeFromParent();
}
cobj->addChild(nativeDelegate);
cobj->setDelegate(nativeDelegate); cobj->setDelegate(nativeDelegate);
nativeDelegate->release();
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE; return JS_TRUE;
} }
@ -64,9 +99,25 @@ static JSBool js_cocos2dx_CCScrollView_setDelegate(JSContext *cx, uint32_t argc,
return JS_FALSE; return JS_FALSE;
} }
class JSB_TableViewDelegate : public CCTableViewDelegate class JSB_TableViewDelegate
: public CCNode
, public CCTableViewDelegate
{ {
public: public:
JSB_TableViewDelegate()
: m_pJSDelegate(NULL)
, m_bNeedUnroot(false)
{}
virtual ~JSB_TableViewDelegate()
{
if (m_bNeedUnroot)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_RemoveObjectRoot(cx, &m_pJSDelegate);
}
}
virtual void scrollViewDidScroll(CCScrollView* view) virtual void scrollViewDidScroll(CCScrollView* view)
{ {
callJSDelegate(view, "scrollViewDidScroll"); callJSDelegate(view, "scrollViewDidScroll");
@ -100,6 +151,15 @@ public:
void setJSDelegate(JSObject* pJSDelegate) void setJSDelegate(JSObject* pJSDelegate)
{ {
m_pJSDelegate = pJSDelegate; m_pJSDelegate = pJSDelegate;
// Check whether the js delegate is a pure js object.
js_proxy_t* p = jsb_get_js_proxy(m_pJSDelegate);
if (!p)
{
m_bNeedUnroot = true;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_AddNamedObjectRoot(cx, &m_pJSDelegate, "TableViewDelegate");
}
} }
@ -129,6 +189,7 @@ private:
} }
JSObject* m_pJSDelegate; JSObject* m_pJSDelegate;
bool m_bNeedUnroot;
}; };
static JSBool js_cocos2dx_CCTableView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp) static JSBool js_cocos2dx_CCTableView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)
@ -144,8 +205,18 @@ static JSBool js_cocos2dx_CCTableView_setDelegate(JSContext *cx, uint32_t argc,
JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]); JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]);
JSB_TableViewDelegate* nativeDelegate = new JSB_TableViewDelegate(); JSB_TableViewDelegate* nativeDelegate = new JSB_TableViewDelegate();
nativeDelegate->setJSDelegate(jsDelegate); nativeDelegate->setJSDelegate(jsDelegate);
JSB_TableViewDelegate* oldDelegate = (JSB_TableViewDelegate*)cobj->getDelegate();
if (oldDelegate)
{
oldDelegate->removeFromParent();
}
cobj->addChild(nativeDelegate);
cobj->setDelegate(nativeDelegate); cobj->setDelegate(nativeDelegate);
nativeDelegate->release();
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE; return JS_TRUE;
} }
@ -153,9 +224,25 @@ static JSBool js_cocos2dx_CCTableView_setDelegate(JSContext *cx, uint32_t argc,
return JS_FALSE; return JS_FALSE;
} }
class JSB_TableViewDataSource : public CCTableViewDataSource class JSB_TableViewDataSource
: public CCNode
, public CCTableViewDataSource
{ {
public: public:
JSB_TableViewDataSource()
: m_pJSTableViewDataSource(NULL)
, m_bNeedUnroot(false)
{}
virtual ~JSB_TableViewDataSource()
{
if (m_bNeedUnroot)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_RemoveObjectRoot(cx, &m_pJSTableViewDataSource);
}
}
virtual CCSize tableCellSizeForIndex(CCTableView *table, unsigned int idx) virtual CCSize tableCellSizeForIndex(CCTableView *table, unsigned int idx)
{ {
jsval ret; jsval ret;
@ -211,6 +298,15 @@ public:
void setTableViewDataSource(JSObject* pJSSource) void setTableViewDataSource(JSObject* pJSSource)
{ {
m_pJSTableViewDataSource = pJSSource; m_pJSTableViewDataSource = pJSSource;
// Check whether the js delegate is a pure js object.
js_proxy_t* p = jsb_get_js_proxy(m_pJSTableViewDataSource);
if (!p)
{
m_bNeedUnroot = true;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_AddNamedObjectRoot(cx, &m_pJSTableViewDataSource, "TableViewDataSource");
}
} }
private: private:
@ -273,6 +369,7 @@ private:
private: private:
JSObject* m_pJSTableViewDataSource; JSObject* m_pJSTableViewDataSource;
bool m_bNeedUnroot;
}; };
static JSBool js_cocos2dx_CCTableView_setDataSource(JSContext *cx, uint32_t argc, jsval *vp) static JSBool js_cocos2dx_CCTableView_setDataSource(JSContext *cx, uint32_t argc, jsval *vp)
@ -284,11 +381,19 @@ static JSBool js_cocos2dx_CCTableView_setDataSource(JSContext *cx, uint32_t argc
JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
if (argc == 1) if (argc == 1)
{ {
CCTableViewDataSource* pOldDataSource = cobj->getDataSource();
CC_SAFE_DELETE(pOldDataSource);
JSB_TableViewDataSource* pNativeSource = new JSB_TableViewDataSource(); JSB_TableViewDataSource* pNativeSource = new JSB_TableViewDataSource();
pNativeSource->setTableViewDataSource(JSVAL_TO_OBJECT(argv[0])); pNativeSource->setTableViewDataSource(JSVAL_TO_OBJECT(argv[0]));
JSB_TableViewDataSource* oldDataSource = (JSB_TableViewDataSource*)cobj->getDataSource();
if (oldDataSource)
{
oldDataSource->removeFromParent();
}
cobj->addChild(pNativeSource);
cobj->setDataSource(pNativeSource); cobj->setDataSource(pNativeSource);
pNativeSource->release();
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE; return JS_TRUE;
} }
@ -310,8 +415,16 @@ static JSBool js_cocos2dx_CCTableView_create(JSContext *cx, uint32_t argc, jsval
ok &= jsval_to_ccsize(cx, argv[1], &arg1); ok &= jsval_to_ccsize(cx, argv[1], &arg1);
cocos2d::extension::CCTableView* ret = NULL; cocos2d::extension::CCTableView* ret = NULL;
ret = new CCTableView(); ret = new CCTableView();
ret->setDataSource(pNativeSource);
ret->autorelease(); ret->autorelease();
JSB_TableViewDataSource* oldDataSource = (JSB_TableViewDataSource*)ret->getDataSource();
if (oldDataSource)
{
oldDataSource->removeFromParent();
}
ret->setDataSource(pNativeSource);
jsval jsret; jsval jsret;
do { do {
if (ret) { if (ret) {
@ -341,6 +454,9 @@ static JSBool js_cocos2dx_CCTableView_create(JSContext *cx, uint32_t argc, jsval
} }
ret->reloadData(); ret->reloadData();
ret->addChild(pNativeSource);
pNativeSource->release();
JS_SET_RVAL(cx, vp, jsret); JS_SET_RVAL(cx, vp, jsret);
return JS_TRUE; return JS_TRUE;
} }
@ -349,9 +465,25 @@ static JSBool js_cocos2dx_CCTableView_create(JSContext *cx, uint32_t argc, jsval
return JS_FALSE; return JS_FALSE;
} }
class JSB_EditBoxDelegate : public CCEditBoxDelegate class JSB_EditBoxDelegate
: public CCNode
, public CCEditBoxDelegate
{ {
public: public:
JSB_EditBoxDelegate()
: m_pJSDelegate(NULL)
, m_bNeedUnroot(false)
{}
virtual ~JSB_EditBoxDelegate()
{
if (m_bNeedUnroot)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_RemoveObjectRoot(cx, &m_pJSDelegate);
}
}
virtual void editBoxEditingDidBegin(CCEditBox* editBox) virtual void editBoxEditingDidBegin(CCEditBox* editBox)
{ {
js_proxy_t * p = jsb_get_native_proxy(editBox); js_proxy_t * p = jsb_get_native_proxy(editBox);
@ -395,9 +527,19 @@ public:
void setJSDelegate(JSObject* pJSDelegate) void setJSDelegate(JSObject* pJSDelegate)
{ {
m_pJSDelegate = pJSDelegate; m_pJSDelegate = pJSDelegate;
// Check whether the js delegate is a pure js object.
js_proxy_t* p = jsb_get_js_proxy(m_pJSDelegate);
if (!p)
{
m_bNeedUnroot = true;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS_AddNamedObjectRoot(cx, &m_pJSDelegate, "TableViewDelegate");
}
} }
private: private:
JSObject* m_pJSDelegate; JSObject* m_pJSDelegate;
bool m_bNeedUnroot;
}; };
static JSBool js_cocos2dx_CCEditBox_setDelegate(JSContext *cx, uint32_t argc, jsval *vp) static JSBool js_cocos2dx_CCEditBox_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)
@ -413,8 +555,17 @@ static JSBool js_cocos2dx_CCEditBox_setDelegate(JSContext *cx, uint32_t argc, js
JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]); JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]);
JSB_EditBoxDelegate* nativeDelegate = new JSB_EditBoxDelegate(); JSB_EditBoxDelegate* nativeDelegate = new JSB_EditBoxDelegate();
nativeDelegate->setJSDelegate(jsDelegate); nativeDelegate->setJSDelegate(jsDelegate);
JSB_EditBoxDelegate* oldDelegate = (JSB_EditBoxDelegate*)cobj->getDelegate();
if (oldDelegate)
{
oldDelegate->removeFromParent();
}
cobj->addChild(nativeDelegate);
cobj->setDelegate(nativeDelegate); cobj->setDelegate(nativeDelegate);
nativeDelegate->release();
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE; return JS_TRUE;
} }

View File

@ -41,7 +41,7 @@ skip = CCBReader::[^CCBReader$ addOwnerCallbackName isJSControlled readByte getC
CC.*Delegate::[*], CC.*Delegate::[*],
CC.*Loader.*::[*], CC.*Loader.*::[*],
*::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType], *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType],
CCEditBox::[setDelegate ^keyboard.* touchDownAction getScriptEditBoxHandler registerScriptEditBoxHandler unregisterScriptEditBoxHandler], CCEditBox::[(g|s)etDelegate ^keyboard.* touchDownAction getScriptEditBoxHandler registerScriptEditBoxHandler unregisterScriptEditBoxHandler],
CCTableView::[create (g|s)etDataSource$ (g|s)etDelegate], CCTableView::[create (g|s)etDataSource$ (g|s)etDelegate],
CCControl::[removeHandleOfControlEvent addHandleOfControlEvent] CCControl::[removeHandleOfControlEvent addHandleOfControlEvent]