2012-08-28 10:22:36 +08:00
|
|
|
#ifndef __SPIDERMONKEY_SPECIFICS_H__
|
|
|
|
#define __SPIDERMONKEY_SPECIFICS_H__
|
|
|
|
|
|
|
|
#include "jsapi.h"
|
2013-04-08 11:56:04 +08:00
|
|
|
#include "support/data_support/uthash.h"
|
2012-08-28 10:22:36 +08:00
|
|
|
|
|
|
|
typedef struct js_proxy {
|
|
|
|
void *ptr;
|
|
|
|
JSObject *obj;
|
|
|
|
UT_hash_handle hh;
|
|
|
|
} js_proxy_t;
|
|
|
|
|
|
|
|
extern js_proxy_t *_native_js_global_ht;
|
|
|
|
extern js_proxy_t *_js_native_global_ht;
|
|
|
|
|
|
|
|
typedef struct js_type_class {
|
|
|
|
uint32_t type;
|
|
|
|
JSClass *jsclass;
|
|
|
|
JSObject *proto;
|
|
|
|
JSObject *parentProto;
|
|
|
|
UT_hash_handle hh;
|
|
|
|
} js_type_class_t;
|
|
|
|
|
|
|
|
extern js_type_class_t *_js_global_type_ht;
|
|
|
|
|
|
|
|
template< typename DERIVED >
|
|
|
|
class TypeTest
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static int s_id()
|
|
|
|
{
|
|
|
|
// return id unique for DERIVED
|
|
|
|
// NOT SURE IT WILL BE REALLY UNIQUE FOR EACH CLASS!!
|
2012-08-29 14:52:30 +08:00
|
|
|
/* Commented by James Chen
|
|
|
|
Using 'getHashCodeByString(typeid(*native_obj).name())' instead of 'reinterpret_cast<long>(typeid(*native_obj).name());'.
|
|
|
|
Since on win32 platform, 'reinterpret_cast<long>(typeid(*native_obj).name());' invoking in cocos2d.dll and outside cocos2d.dll(in TestJavascript.exe) will return different address.
|
|
|
|
But the return string from typeid(*native_obj).name() is the same string, so we must convert the string to hash id to make sure we can get unique id.
|
|
|
|
*/
|
|
|
|
// static const long id = reinterpret_cast<long>(typeid( DERIVED ).name());
|
2013-08-22 18:16:50 +08:00
|
|
|
static const long id = typeid( DERIVED ).hash_code();
|
2012-08-28 10:22:36 +08:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char* s_name()
|
|
|
|
{
|
|
|
|
// return id unique for DERIVED
|
|
|
|
// ALWAYS VALID BUT STRING, NOT INT - BUT VALID AND CROSS-PLATFORM/CROSS-VERSION COMPATBLE
|
|
|
|
// AS FAR AS YOU KEEP THE CLASS NAME
|
|
|
|
return typeid( DERIVED ).name();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define JS_NEW_PROXY(p, native_obj, js_obj) \
|
|
|
|
do { \
|
|
|
|
p = (js_proxy_t *)malloc(sizeof(js_proxy_t)); \
|
|
|
|
assert(p); \
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
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); \
|
2012-08-28 10:22:36 +08:00
|
|
|
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); \
|
issue #1581: JSBinding bug fixes.
Some fixes of JSBinding codes:
[1] Check whether the proxy was already added in JS_NEW_PROXY
[2] In struct schedFunc_proxy_t, JSScheduleWrapper* --> CCArray*
Reason: One js function may correspond to many targets. To debug this, you could refer to JSScheduleWrapper::dump function. It will prove that i'm right. :)
[3] In ScriptingCore::cleanupSchedulesAndActions function, we must invoke unschedule for all targets and remove the proxy both in _schedFunc_target_ht and _schedTarget_native_ht, otherwise the hash tables will grow bigger and bigger, so I added a new function JSScheduleWrapper::removeAllTargetsForNatiaveNode to make this things easier.
[4] To easily find out the bugs of binding codes, I add JS_SetGCZeal in ScriptingCore::createGlobalContext, it only works in DEBUG mode.
[5] In js_cocos2dx_CCNode_getChildren, we should add the generated array to root to avoid gc happen when invoking JS_SetElement.
[6] The JSCallFuncWrapper isn't needed since an action will be run by a cc.Node and it will be released at the CCNode::cleanup.
[7] Some improvements of JSScheduleWrapper class.
[8] Added a new function JSScheduleWrapper::setTarget, it's for js_CCNode_unschedule to find out which target need to be unscheduled.
[9] Commented JS_SetReservedSlot in js_CCNode_scheduleOnce and js_CCNode_schedule.
Reason:
For js_CCNode_scheduleOnce: Don't add the callback function to the reserved slot of this js object.Since the class of js object may be inherited from cocos class(e.g. cc.Sprite). The subclass will not contain reserved slots. It will crash if invoking this.
For js_CCNode_schedule: Don't add js callback function to the reserved slot of scheduler js object. Since the scheduler is an object always rooted.
So the callback function might not be released when gc comes.I looked inside the implementation of cc.Node.schedule, and it doesn't use JS_SetReservedSlot there.
2012-11-28 22:04:55 +08:00
|
|
|
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); \
|
2012-08-28 10:22:36 +08:00
|
|
|
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 { \
|
2012-09-19 09:44:21 +08:00
|
|
|
if (nproxy) { HASH_DEL(_native_js_global_ht, nproxy); free(nproxy); } \
|
|
|
|
if (jsproxy) { HASH_DEL(_js_native_global_ht, jsproxy); free(jsproxy); } \
|
2012-08-28 10:22:36 +08:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define TEST_NATIVE_OBJECT(cx, native_obj) \
|
|
|
|
if (!native_obj) { \
|
|
|
|
JS_ReportError(cx, "Invalid Native Object"); \
|
|
|
|
return JS_FALSE; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|