Sync issue fixes from creator (#17041)

* Add EventDispatcher#hasEventListener (sync from creator)

* Fix function wrapper using js object during its gc

* Support more system languages

* Direct log/error for better understanding problems & add sys.now

* Synchronize Editbox APIs

* Synchronize Scheduler.PRIORITY_NON_SYSTEM const

* Upgrade web engine

* Upgrade test cases

* Manually bind EventDispatcher::addCustomEventListener to avoid memory issue

* Manual bind EventListeners’ create to avoid memory issue

* Fix compilation issue when COCOS_DEBUG = 2

* Unify function name of Texture2D::releaseTexture

* Fix compilation issues and update web & bindings-generator

* Fix lua compilation issue

* Use %ld instead of %zd

* Separate FinalizeHook for ref objects and non ref objects

* Fix spine TrackEntry recursive conversion issue by using getter

* Fix crash during Wrappers deallocation (possible to have leak)

* Increase default JS heap to 32 mb

* Update engine version

* Add change log of web engine

* Improve cc.formatStr

* Fix chipmunk crash issues when using setDefaultCollisionHandler

* Add change log for JSB and update web engine ref
This commit is contained in:
pandamicro 2016-12-21 13:39:34 +08:00 committed by minggo
parent bd0789e22c
commit a715e3169f
18 changed files with 381 additions and 194 deletions

View File

@ -5,13 +5,14 @@ coocs2d-x-3.14 Dec 19 2016
[NEW] Action: new actions: ResizeBy and ResizeTo
[NEW] Button: can set title label
[NEW] Can disable multi touch on Android
[NEW] EventDispatcher: Add hasEventListener to check listener existance
[NEW] EditBox: add horizontal text alignment
[NEW] Sprite: support scale9 feature
[NEW] Slider: add methods to get _slidBallNormalRenderer
[NEW] Desktop: add a method to toggle between fullscreen and windowed
[NEW] Desktop: add events for window resize, focus and unfocus
[NEW] Mac: supports game controller
[NEW] JSB: add perfromance.now()
[NEW] JSB: add cc.sys.now() and perfromance.now(), the last one is more accurate
[NEW] Lua: add cc.vec3 functions: add, sub and dot
[NEW] Lua: use luajit 2.1.0-beta2
@ -25,6 +26,18 @@ coocs2d-x-3.14 Dec 19 2016
[REFINE] Mac: system font enhancement
[REFINE] Linux: build shared lib with -fPIC
[REFINE] Android: use SharedPreferences.apply() to store data
[REFINE] JSB: Increase default JS heap to 32 mb
[REFINE] JSB: Support more system languages
[REFINE] JSB: Direct log/error for better understantding problems
[REFINE] JSB: Separate FinalizeHook for ref objects and non ref objects
[REFINE] Web: Improve overall node construction performance
[REFINE] Web: Improve overall loading process performance
[REFINE] Web: Reduce overall memory usage
[REFINE] Web: Made cc.LabelBMFont and cc.LabelAtlas support texture packing and auto batching
[REFINE] Web: Reimplement a much faster ccui.Scale9Sprite
[REFINE] Web: Reimplement a much faster cc.DrawNode WebGL renderer
[REFINE] Web: Use stack to avoid recursive call in transform, onEnter, onExit etc, reduce call stack depth
[FIX] AsstsManagerEx: project.manifest may be downloaded twice
[FIX] AudioEngine: can not play large ogg file
@ -74,11 +87,25 @@ coocs2d-x-3.14 Dec 19 2016
[FIX] Linux: Application::openURL can not work
[FIX] Desktop: crash upon exit when NotificationNode exists
[FIX] Spine: color bug
[FIX] Console: doesn't support `--ap` parameter
[FIX] Lua: result of radian2angle is wrong
[FIX] Lua: iskindof_ doesn't work correctly
[FIX] Lua: new lua project crashes compiling with VS2015 release mode
[FIX] JSB: `jsb.addRoot is not a function` error caused by cc.GLProgramState.setUniformCallback
[FIX] Console: doesn't support `--ap` parameter
[FIX] JSB: Fix spine TrackEntry conversion crash issue
[FIX] JSB: Fix CallbackWrapper and FunctionWrapper crash during deallocation in new memory model
[FIX] JSB: Fix event object memory issue by manually bind EventDispatcher::addCustomEventListener
[FIX] JSB: Fix chipmunk crash issues when using setDefaultCollisionHandler
[FIX] JSB: Fix compilation issues when COCOS_DEBUG = 2
[FIX] JSB: Unify function name of Texture2D::releaseTexture
[FIX] Web: Fix spine blend function inconsistency between web and jsb
[FIX] Web: Fix particle system load from plist generated by x-studio365
[FIX] Web: Fix doEnumerateRecursive(node, name, callback) always return undefined issue
[FIX] Web: Change bright style on 'setEnabled' call of ccui.Widget
[FIX] Web: Fix Editbox can't input in full screen mode
[FIX] Web: Fix texture issue on some Android devices by always set vertexAttribPointer
[FIX] Web: Made xhr ontimeout callback work on all browsers
[FIX] Web: Fix clear color not normalized issue
cocos2d-x-3.13.1 Sep 13 2016

View File

@ -365,7 +365,7 @@ void GLView::handleTouchesMove(int num, intptr_t ids[], float xs[], float ys[],
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];
if (touch)
{
@ -417,7 +417,7 @@ void GLView::handleTouchesOfEndOrCancel(EventTouch::EventCode eventCode, int num
Touch* touch = g_touches[iter->second];
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,
(y - _viewPortRect.origin.y) / _scaleY);

View File

@ -631,14 +631,14 @@ void ScriptingCore::createGlobalContext() {
// Removed from Spidermonkey 19.
//JS_SetCStringsAreUTF8();
_rt = JS_NewRuntime(8L * 1024L * 1024L);
_rt = JS_NewRuntime(32L * 1024L * 1024L);
JS_SetGCParameter(_rt, JSGC_MAX_BYTES, 0xffffffff);
JS_SetTrustedPrincipals(_rt, &shellTrustedPrincipals);
JS_SetSecurityCallbacks(_rt, &securityCallbacks);
JS_SetNativeStackQuota(_rt, JSB_MAX_STACK_QUOTA);
_cx = JS_NewContext(_rt, 8192);
_cx = JS_NewContext(_rt, 32 * 1024);
// Removed in Firefox v27
// JS_SetOptions(this->_cx, JSOPTION_TYPE_INFERENCE);
@ -1438,7 +1438,7 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
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))
{
break;
@ -1451,7 +1451,7 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
{
jsval dataVal[2];
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);
}
@ -1459,7 +1459,6 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
{
removeJSObject(_cx, touch);
}
removeJSObject(_cx, event);
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);
jsval dataVal[2];
dataVal[0] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, touch, typeClassTouch, "cocos2d::Touch"));
dataVal[1] = OBJECT_TO_JSVAL(jsb_get_or_create_weak_jsobject(_cx, event, typeClassEvent, "cocos2d::EventTouch"));
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));
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)
{
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);
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);
jsval args[2] = {
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)
@ -1662,7 +1661,7 @@ int ScriptingCore::executeCustomTouchesEvent(EventTouch::EventCode eventType,
{
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);
if (!JS_SetElement(this->_cx, jsretArr, count, jsval)) {
break;
@ -1690,7 +1689,7 @@ int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType, Touc
std::string funcName = getTouchFuncName(eventType);
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);
@ -1709,7 +1708,7 @@ int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType,
std::string funcName = getTouchFuncName(eventType);
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);
@ -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 jsObj(cx, JS_NewObject(cx, typeClass->jsclass, proto, parent));
auto proxy = jsb_new_proxy(native, jsObj);
js_add_FinalizeHook(cx, jsObj, false);
#if ! CC_ENABLE_GC_FOR_NATIVE_OBJECTS
JS::AddNamedObjectRoot(cx, &proxy->obj, debug);
#else
#if COCOS2D_DEBUG > 1
CCLOG("++++++WEAK_REF++++++ Cpp(%s): %p - JS: %p", debug, native, jsObj.get());
if (debug != nullptr)
{
CCLOG("++++++WEAK_REF++++++ Cpp(%s): %p - JS: %p", debug, native, jsObj.get());
}
#endif // COCOS2D_DEBUG
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
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);
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
ref->retain();
js_add_FinalizeHook(cx, jsObj);
js_add_FinalizeHook(cx, jsObj, true);
#if COCOS2D_DEBUG > 1
CCLOG("++++++RETAINED++++++ Cpp(%s): %p - JS: %p", debug, ref, jsObj.get());
#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
(void)ref;
JS::RootedObject jsObj(cx, *obj);
js_add_FinalizeHook(cx, jsObj);
js_add_FinalizeHook(cx, jsObj, true);
// don't retain it, already retained
#if COCOS2D_DEBUG > 1
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;
ref->retain();
JS::RootedObject jsObj(cx, *obj);
js_add_FinalizeHook(cx, jsObj);
js_add_FinalizeHook(cx, jsObj, true);
#else
// don't autorelease it, since it is already autoreleased
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
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);
#endif
}

View File

@ -41,7 +41,7 @@
#include <memory>
#include <chrono>
#define ENGINE_VERSION "Cocos2d-JS v3.13"
#define ENGINE_VERSION "Cocos2d-JS v3.14"
void js_log(const char *format, ...);
@ -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
* 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.
@ -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 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,

View File

@ -824,6 +824,7 @@ jsval cpSegmentQueryInfo_to_jsval(JSContext *cx, cpSegmentQueryInfo segmentQuery
return OBJECT_TO_JSVAL(object);
}
#pragma mark - Collision Handler
struct collision_handler {
@ -845,39 +846,72 @@ struct collision_handler {
unsigned int is_oo; // Objected oriented API ?
UT_hash_handle hh;
bool is_default;
collision_handler()
collision_handler ()
{
begin = nullptr;
pre = nullptr;
post = nullptr;
separate = nullptr;
jsthis = nullptr;
is_default = false;
}
~collision_handler ()
{
JS::RootedValue jsspace(cx, OBJECT_TO_JSVAL(jsthis));
if (!is_default && jsspace.isObject())
{
JS::RootedValue callback(cx);
callback.set(OBJECT_TO_JSVAL(begin));
if (callback.isObject())
{
js_remove_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(pre));
if (callback.isObject())
{
js_remove_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(post));
if (callback.isObject())
{
js_remove_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(separate));
if (callback.isObject())
{
js_remove_object_reference(jsspace, callback);
}
}
}
// Space must be set after set handles
void setJSSpace(JS::HandleValue jsspace)
{
if (!jsspace.isNullOrUndefined())
if (jsspace.isObject())
{
jsthis = jsspace.toObjectOrNull();
JS::RootedValue callback(ScriptingCore::getInstance()->getGlobalContext());
JS::RootedValue callback(cx);
callback.set(OBJECT_TO_JSVAL(begin));
if (!callback.isNullOrUndefined())
if (callback.isObject())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(pre));
if (!callback.isNullOrUndefined())
if (callback.isObject())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(post));
if (!callback.isNullOrUndefined())
if (callback.isObject())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(separate));
if (!callback.isNullOrUndefined())
if (callback.isObject())
{
js_add_object_reference(jsspace, callback);
}
@ -900,7 +934,12 @@ static unsigned long pair_ints( unsigned long A, unsigned long B )
static cpBool myCollisionBegin(cpArbiter *arb, cpSpace *space, void *data)
{
if (data == nullptr) {
return cpTrue;
}
struct collision_handler *handler = (struct collision_handler*) data;
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
jsval args[2];
if( handler->is_oo ) {
@ -913,8 +952,6 @@ static cpBool myCollisionBegin(cpArbiter *arb, cpSpace *space, void *data)
args[1] = opaque_to_jsval(handler->cx, space );
}
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue rval(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jsbegin(handler->cx, OBJECT_TO_JSVAL(handler->begin));
@ -930,7 +967,12 @@ static cpBool myCollisionBegin(cpArbiter *arb, cpSpace *space, void *data)
static cpBool myCollisionPre(cpArbiter *arb, cpSpace *space, void *data)
{
if (data == nullptr) {
return cpTrue;
}
struct collision_handler *handler = (struct collision_handler*) data;
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
jsval args[2];
if( handler->is_oo ) {
@ -943,8 +985,6 @@ static cpBool myCollisionPre(cpArbiter *arb, cpSpace *space, void *data)
args[1] = opaque_to_jsval( handler->cx, space );
}
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue rval(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jspre(handler->cx, OBJECT_TO_JSVAL(handler->pre));
@ -960,7 +1000,12 @@ static cpBool myCollisionPre(cpArbiter *arb, cpSpace *space, void *data)
static void myCollisionPost(cpArbiter *arb, cpSpace *space, void *data)
{
if (data == nullptr) {
return;
}
struct collision_handler *handler = (struct collision_handler*) data;
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
jsval args[2];
@ -974,8 +1019,6 @@ static void myCollisionPost(cpArbiter *arb, cpSpace *space, void *data)
args[1] = opaque_to_jsval( handler->cx, space );
}
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue ignore(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jspost(handler->cx, OBJECT_TO_JSVAL(handler->post));
@ -986,27 +1029,35 @@ static void myCollisionPost(cpArbiter *arb, cpSpace *space, void *data)
static void myCollisionSeparate(cpArbiter *arb, cpSpace *space, void *data)
{
struct collision_handler *handler = (struct collision_handler*) data;
if(! handler->cx || !handler->space)
if (handler == nullptr || !handler->cx || !handler->space)
return;
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue jssep(handler->cx, OBJECT_TO_JSVAL(handler->separate));
if (!jssep.isObject())
{
return;
}
jsval args[2];
if( handler->is_oo ) {
if (handler->is_oo)
{
JS::RootedObject arbiterProto(handler->cx, JSB_cpArbiter_object);
JS::RootedObject spaceProto(handler->cx, JSB_cpSpace_object);
args[0] = c_class_to_jsval(handler->cx, arb, arbiterProto, JSB_cpArbiter_class, "cpArbiter");
args[1] = c_class_to_jsval(handler->cx, space, spaceProto, JSB_cpSpace_class, "cpArbiter");
} else {
} else
{
args[0] = opaque_to_jsval( handler->cx, arb);
args[1] = opaque_to_jsval( handler->cx, space );
}
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue ignore(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jssep(handler->cx, OBJECT_TO_JSVAL(handler->separate));
bool ok = JS_CallFunctionValue( handler->cx, jsthis, jssep, JS::HandleValueArray::fromMarkedLocation(2, args), &ignore);
JSB_PRECONDITION2(ok, handler->cx, , "Error calling collision callback: Separate");}
JSB_PRECONDITION2(ok, handler->cx, , "Error calling collision callback: Separate");
}
#pragma mark - cpSpace
@ -1015,22 +1066,33 @@ static void myCollisionSeparate(cpArbiter *arb, cpSpace *space, void *data)
void JSB_cpSpace_finalize(JSFreeOp *fop, JSObject *jsthis)
{
struct jsb_c_proxy_s *proxy = jsb_get_c_proxy_for_jsobject(jsthis);
if ( proxy ) {
if ( proxy )
{
CCLOGINFO("jsbindings: finalizing JS object %p (cpSpace), handle: %p", jsthis, proxy->handle);
// space
cpSpace *space = (cpSpace*) proxy->handle;
// Remove collision handlers, since the user might have forgotten to manually remove them
struct collision_handler *current = nullptr, *tmp = nullptr;
HASH_ITER(hh, collision_handler_hash, current, tmp) {
if( current->space == space ) {
HASH_ITER(hh, collision_handler_hash, current, tmp)
{
if( current->space == space )
{
if (current->is_default)
{
cpCollisionHandler* defaultHandler = cpSpaceAddDefaultCollisionHandler(space);
defaultHandler->userData = nullptr;
defaultHandler->beginFunc = cpCollisionHandlerDoNothing.beginFunc;
defaultHandler->preSolveFunc = cpCollisionHandlerDoNothing.preSolveFunc;
defaultHandler->postSolveFunc = cpCollisionHandlerDoNothing.postSolveFunc;
defaultHandler->separateFunc = cpCollisionHandlerDoNothing.separateFunc;
}
HASH_DEL(collision_handler_hash,current); /* delete; users advances to next */
delete current; /* optional- if you want to free */
}
}
// Free Space Children
freeSpaceChildren(space);
@ -1064,13 +1126,13 @@ bool __jsb_cpSpace_addCollisionHandler(JSContext *cx, jsval *vp, jsval *argvp, J
ok &= jsval_to_int(cx, jstypeA, (int32_t*) &handler->typeA );
ok &= jsval_to_int(cx, jstypeB, (int32_t*) &handler->typeB );
handler->begin = argvp->toObjectOrNull();
handler->begin = argvp->isObject() ? argvp->toObjectOrNull() : nullptr;
argvp++;
handler->pre = argvp->toObjectOrNull();
handler->pre = argvp->isObject() ? argvp->toObjectOrNull() : nullptr;
argvp++;
handler->post = argvp->toObjectOrNull();
handler->post = argvp->isObject() ? argvp->toObjectOrNull() : nullptr;
argvp++;
handler->separate = argvp->toObjectOrNull();
handler->separate = argvp->isObject() ? argvp->toObjectOrNull() : nullptr;
argvp++;
JS::RootedValue spaceVal(cx, OBJECT_TO_JSVAL(jsspace));
@ -1154,25 +1216,27 @@ bool JSB_cpSpace_setDefaultCollisionHandler(JSContext *cx, uint32_t argc, jsval
handler->typeA = 0;
handler->typeB = 0;
handler->begin = args.get(0).toObjectOrNull();
handler->pre = args.get(1).toObjectOrNull();
handler->post = args.get(2).toObjectOrNull();
handler->separate = args.get(3).toObjectOrNull();
handler->begin = args.get(0).isObject() ? args.get(0).toObjectOrNull() : nullptr;
handler->pre = args.get(1).isObject() ? args.get(1).toObjectOrNull() : nullptr;
handler->post = args.get(2).isObject() ? args.get(2).toObjectOrNull() : nullptr;
handler->separate = args.get(3).isObject() ? args.get(3).toObjectOrNull() : nullptr;
JS::RootedValue spaceVal(cx, OBJECT_TO_JSVAL(jsthis));
// Space must be set after set handles
handler->setJSSpace(spaceVal);
// Object Oriented API ?
handler->is_oo = 1;
// Default handler shouldn't be removed
handler->is_default = true;
// owner of the collision handler
handler->space = space;
handler->cx = cx;
cpCollisionHandler* defaultHandler = cpSpaceAddDefaultCollisionHandler(space);
defaultHandler->beginFunc = !handler->begin ? NULL : &myCollisionBegin;
defaultHandler->preSolveFunc = !handler->pre ? NULL : &myCollisionPre;
defaultHandler->postSolveFunc = !handler->post ? NULL : &myCollisionPost;
defaultHandler->separateFunc = !handler->separate ? NULL : &myCollisionSeparate;
defaultHandler->beginFunc = !handler->begin ? cpCollisionHandlerDoNothing.beginFunc : &myCollisionBegin;
defaultHandler->preSolveFunc = !handler->pre ? cpCollisionHandlerDoNothing.preSolveFunc : &myCollisionPre;
defaultHandler->postSolveFunc = !handler->post ? cpCollisionHandlerDoNothing.postSolveFunc : &myCollisionPost;
defaultHandler->separateFunc = !handler->separate ? cpCollisionHandlerDoNothing.separateFunc : &myCollisionSeparate;
defaultHandler->userData = handler;
//
// Already added ? If so, remove it.
@ -2554,7 +2618,7 @@ static void unroot_jsobject_from_handle(void *handle)
static void shapeFreeWrap(cpSpace *space, cpShape *shape, void *unused){
cpSpaceRemoveShape(space, shape);
unroot_jsobject_from_handle(shape);
// cpShapeFree(shape);
// cpShapeFree(shape);
}
static void postShapeFree(cpShape *shape, cpSpace *space){
@ -2564,7 +2628,7 @@ static void postShapeFree(cpShape *shape, cpSpace *space){
static void constraintFreeWrap(cpSpace *space, cpConstraint *constraint, void *unused){
cpSpaceRemoveConstraint(space, constraint);
unroot_jsobject_from_handle(constraint);
// cpConstraintFree(constraint);
// cpConstraintFree(constraint);
}
static void postConstraintFree(cpConstraint *constraint, cpSpace *space){
@ -2574,7 +2638,7 @@ static void postConstraintFree(cpConstraint *constraint, cpSpace *space){
static void bodyFreeWrap(cpSpace *space, cpBody *body, void *unused){
cpSpaceRemoveBody(space, body);
unroot_jsobject_from_handle(body);
// cpBodyFree(body);
// cpBodyFree(body);
}
static void postBodyFree(cpBody *body, cpSpace *space){
@ -2587,7 +2651,6 @@ void static freeSpaceChildren(cpSpace *space)
// Must remove these BEFORE freeing the body or you will access dangling pointers.
cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)postShapeFree, space);
cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)postConstraintFree, space);
cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)postBodyFree, space);
}
@ -2620,4 +2683,4 @@ bool JSB_cpMomentForSegment(JSContext *cx, uint32_t argc, jsval *vp) {
}
#endif // JSB_INCLUDE_CHIPMUNK
#endif // JSB_INCLUDE_CHIPMUNK

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);
}
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_NewObject(cx, jsb_FinalizeHook_class, proto, JS::NullPtr()));
JS::RootedObject hook(cx);
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());
JS::RootedValue hookVal(cx, OBJECT_TO_JSVAL(hook));
JS_SetProperty(cx, target, "__hook", hookVal);
@ -591,6 +600,7 @@ void js_add_object_reference(JS::HandleValue owner, JS::HandleValue target)
ScriptingCore *engine = ScriptingCore::getInstance();
JSContext *cx = engine->getGlobalContext();
JS::RootedObject global(cx, engine->getGlobalObject());
JSAutoCompartment(cx, global);
JS::RootedObject jsbObj(cx);
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(cx, OBJECT_TO_JSVAL(jsbObj));
@ -615,10 +625,11 @@ void js_remove_object_reference(JS::HandleValue owner, JS::HandleValue target)
}
ScriptingCore *engine = ScriptingCore::getInstance();
JSContext *cx = engine->getGlobalContext();
JS::RootedObject global(cx, engine->getGlobalObject());
JSAutoCompartment(cx, global);
JS::RootedObject ownerObj(cx, owner.toObjectOrNull());
JS::RootedObject targetObj(cx, target.toObjectOrNull());
JS::RootedObject global(cx, engine->getGlobalObject());
JS::RootedObject jsbObj(cx);
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(cx, OBJECT_TO_JSVAL(jsbObj));
@ -645,6 +656,7 @@ void js_add_object_root(JS::HandleValue target)
ScriptingCore *engine = ScriptingCore::getInstance();
JSContext *cx = engine->getGlobalContext();
JS::RootedObject global(cx, engine->getGlobalObject());
JSAutoCompartment(cx, global);
JS::RootedObject jsbObj(cx);
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(cx, OBJECT_TO_JSVAL(jsbObj));
@ -673,6 +685,8 @@ void js_remove_object_root(JS::HandleValue target)
}
ScriptingCore *engine = ScriptingCore::getInstance();
JSContext *cx = engine->getGlobalContext();
JS::RootedObject global(cx, engine->getGlobalObject());
JSAutoCompartment(cx, global);
JS::RootedObject targetObj(cx, target.toObjectOrNull());
js_proxy_t *pTarget = jsb_get_js_proxy(targetObj);
if (!pTarget)
@ -680,7 +694,6 @@ void js_remove_object_root(JS::HandleValue target)
return;
}
JS::RootedObject global(cx, engine->getGlobalObject());
JS::RootedObject jsbObj(cx);
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(cx, OBJECT_TO_JSVAL(jsbObj));
@ -703,6 +716,7 @@ void js_remove_object_root(JS::HandleValue target)
}
JSCallbackWrapper::JSCallbackWrapper()
: _rooted(true)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_jsCallback = JS::NullValue();
@ -716,6 +730,7 @@ JSCallbackWrapper::JSCallbackWrapper()
}
JSCallbackWrapper::JSCallbackWrapper(JS::HandleValue owner)
: _rooted(true)
{
_owner = owner;
_jsCallback = JS::NullValue();
@ -727,7 +742,7 @@ JSCallbackWrapper::~JSCallbackWrapper()
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
if (_rooted && !ownerVal.isNullOrUndefined())
{
JS::RootedValue target(cx, _jsCallback);
if (!target.isNullOrUndefined())
@ -1229,7 +1244,7 @@ void JSScheduleWrapper::dump()
schedFunc_proxy_t *current_func, *tmp_func;
int jsfuncTargetCount = 0;
HASH_ITER(hh, _schedFunc_target_ht, current_func, tmp_func) {
auto targets = current->targets;
auto targets = current_func->targets;
for (const auto& pObj : *targets)
{
CCLOG("js func ( %p ), native target[%d]=( %p )", current_func->jsfuncObj, jsfuncTargetCount, pObj);
@ -1328,7 +1343,7 @@ bool js_CCNode_unschedule(JSContext *cx, uint32_t argc, jsval *vp)
auto targetArray = JSScheduleWrapper::getTargetForSchedule(args.get(0));
if (targetArray) {
CCLOGINFO("unschedule target number: %ld", static_cast<long>(targetArray->count()));
CCLOGINFO("unschedule target number: %ld", static_cast<long>(targetArray->size()));
for (const auto& tmp : *targetArray)
{
@ -1707,7 +1722,7 @@ bool js_cocos2dx_CCNode_scheduleUpdate(JSContext *cx, uint32_t argc, jsval *vp)
if (!bFound)
{
tmpCobj = new (std::nothrow) JSScheduleWrapper(thisValue);
tmpCobj = new (std::nothrow) JSScheduleWrapper(JS::NullHandleValue);
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(thisValue);
tmpCobj->setJSCallbackFunc(jsUpdateFunc);
@ -5876,15 +5891,17 @@ bool js_cocos2dx_ComponentJS_getScriptObject(JSContext *cx, uint32_t argc, jsval
return false;
}
JSClass *jsb_FinalizeHook_class;
JSObject *jsb_FinalizeHook_prototype;
JSClass *jsb_RefFinalizeHook_class;
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);
// Create new object
JS::RootedObject proto(cx, jsb_FinalizeHook_prototype);
JS::RootedObject obj(cx, JS_NewObject(cx, jsb_FinalizeHook_class, proto, JS::NullPtr()));
JS::RootedObject proto(cx, jsb_RefFinalizeHook_prototype);
JS::RootedObject obj(cx, JS_NewObject(cx, jsb_RefFinalizeHook_class, proto, JS::NullPtr()));
// Register arguments[0] as owner
if (!args.get(0).isNullOrUndefined())
{
@ -5893,7 +5910,7 @@ static bool jsb_FinalizeHook_constructor(JSContext *cx, uint32_t argc, jsval *vp
args.rval().set(OBJECT_TO_JSVAL(obj));
return true;
}
void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
void jsb_RefFinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
{
ScriptingCore *sc = ScriptingCore::getInstance();
JSContext *cx = sc->getGlobalContext();
@ -5902,7 +5919,7 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
if (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* jsproxy = nullptr;
jsproxy = jsb_get_js_proxy(owner);
@ -5931,11 +5948,6 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
CCLOG("------RELEASED------ Cpp: %p - JS: %p", refObj, ownerPtr);
#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);
}
#if COCOS2D_DEBUG > 1
@ -5945,24 +5957,83 @@ void jsb_FinalizeHook_finalize(JSFreeOp *fop, JSObject *obj)
#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);
nproxy = jsb_get_native_proxy(jsproxy->ptr);
jsb_remove_proxy(nproxy, jsproxy);
#if COCOS2D_DEBUG > 1
CCLOG("------WEAK_REF------ Cpp: %p - JS: %p", nproxy->ptr, ownerPtr);
#endif // COCOS2D_DEBUG
sc->setFinalizing(nullptr);
}
}
}
void jsb_register_FinalizeHook(JSContext *cx, JS::HandleObject global) {
jsb_FinalizeHook_class = (JSClass *)calloc(1, sizeof(JSClass));
jsb_FinalizeHook_class->name = "FinalizeHook";
jsb_FinalizeHook_class->addProperty = JS_PropertyStub;
jsb_FinalizeHook_class->delProperty = JS_DeletePropertyStub;
jsb_FinalizeHook_class->getProperty = JS_PropertyStub;
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);
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_FinalizeHook_prototype = JS_InitClass(cx, global,
jsb_RefFinalizeHook_prototype = JS_InitClass(cx, global,
JS::NullPtr(), // parent proto
jsb_FinalizeHook_class,
jsb_FinalizeHook_constructor, 0, // constructor
jsb_RefFinalizeHook_class,
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);
}
@ -5976,7 +6047,8 @@ void register_cocos2dx_js_core(JSContext* cx, JS::HandleObject global)
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
// 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_AutoPolygon(cx, jsbObj);

View File

@ -79,8 +79,10 @@ extern schedFunc_proxy_t *_schedFunc_target_ht;
extern schedTarget_proxy_t *_schedObj_target_ht;
extern callfuncTarget_proxy_t *_callfuncTarget_native_ht;
extern JSClass *jsb_FinalizeHook_class;
extern JSObject *jsb_FinalizeHook_prototype;
extern JSClass *jsb_RefFinalizeHook_class;
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
@ -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.
* 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_remove_object_reference(JS::HandleValue owner, JS::HandleValue target);
@ -170,6 +172,7 @@ protected:
JS::Heap<JS::Value> _jsCallback;
JS::Heap<JS::Value> _jsThisObj;
JS::Heap<JS::Value> _extraData;
bool _rooted;
};

View File

@ -30,7 +30,6 @@ class JSCCBAnimationWrapper: public JSCallbackWrapper
{
public:
JSCCBAnimationWrapper(JS::HandleValue owner) : JSCallbackWrapper(owner) {}
virtual ~JSCCBAnimationWrapper() {}
void animationCompleteCallback()
{

View File

@ -107,6 +107,7 @@ const char* JSStringWrapper::get()
// JSFunctionWrapper
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval)
: _cx(cx)
, _rooted(false)
{
_jsthis = jsthis;
_fval = fval;
@ -128,10 +129,12 @@ JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS:
{
js_add_object_reference(valRoot, funcVal);
}
_rooted = true;
}
}
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval, JS::HandleValue owner)
: _cx(cx)
, _rooted(false)
{
_jsthis = jsthis;
_fval = fval;
@ -154,7 +157,7 @@ JSFunctionWrapper::~JSFunctionWrapper()
{
JS::RootedValue ownerVal(_cx, _owner);
if (!ownerVal.isNullOrUndefined() && ScriptingCore::getInstance()->getFinalizing() != ownerVal.toObjectOrNull())
if (_rooted && !ownerVal.isNullOrUndefined())
{
JS::RootedValue thisVal(_cx, OBJECT_TO_JSVAL(_jsthis));
if (!thisVal.isNullOrUndefined())

View File

@ -85,6 +85,7 @@ private:
JS::Heap<JSObject*> _jsthis;
JS::Heap<JS::Value> _fval;
JS::Heap<JS::Value> _owner;
bool _rooted;
private:
CC_DISALLOW_COPY_AND_ASSIGN(JSFunctionWrapper);
};

View File

@ -179,7 +179,7 @@ bool js_EventListenerAcceleration_create(JSContext *cx, uint32_t argc, jsval *vp
largv[0] = ccacceleration_to_jsval(cx, *acc);
if (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 {
largv[1] = JSVAL_NULL;
};
@ -246,7 +246,7 @@ bool js_EventListenerCustom_create(JSContext *cx, uint32_t argc, jsval *vp)
jsval largv[1];
if (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 {
largv[0] = JSVAL_NULL;
};
@ -298,7 +298,7 @@ bool js_EventDispatcher_addCustomEventListener(JSContext *cx, uint32_t argc, jsv
jsval largv[1];
if (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 {
largv[0] = JSVAL_NULL;
};

View File

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

View File

@ -28,8 +28,6 @@
using namespace spine;
std::unordered_map<spTrackEntry*, jsval> _spTrackEntryMap;
jsval speventdata_to_jsval(JSContext* cx, spEventData& v)
{
JS::RootedObject tmp(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
@ -279,45 +277,68 @@ jsval spanimation_to_jsval(JSContext* cx, spAnimation& v)
return JSVAL_NULL;
}
bool jsb_spine_TrackEntry_get_next(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
{
JS::RootedObject jsthis(cx, obj);
js_proxy_t *proxy = jsb_get_js_proxy(jsthis);
spTrackEntry* cobj = (spTrackEntry *)(proxy ? proxy->ptr : NULL);
if (cobj) {
JS::RootedValue jsret(cx, JS::NullValue());
if (cobj->next)
{
jsret = sptrackentry_to_jsval(cx, *cobj->next);
}
vp.set(jsret);
return true;
}
else {
CCLOGERROR("jsb_spine_TrackEntry_get_next : Invalid Native Object");
return false;
}
}
bool jsb_spine_TrackEntry_get_previous(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
{
JS::RootedObject jsthis(cx, obj);
js_proxy_t *proxy = jsb_get_js_proxy(jsthis);
spTrackEntry* cobj = (spTrackEntry *)(proxy ? proxy->ptr : NULL);
if (cobj) {
JS::RootedValue jsret(cx, JS::NullValue());
if (cobj->previous)
{
jsret = sptrackentry_to_jsval(cx, *cobj->previous);
}
vp.set(jsret);
return true;
}
else {
CCLOGERROR("jsb_spine_TrackEntry_get_previous : Invalid Native Object");
return false;
}
}
jsval sptrackentry_to_jsval(JSContext* cx, spTrackEntry& v)
{
JS::RootedObject tmp(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
if (!tmp) return JSVAL_NULL;
JS::RootedValue nextVal(cx);
if (v.next)
js_proxy_t *proxy = jsb_get_native_proxy(&v);
if (proxy)
{
auto nextPtr = v.next;
auto entry = _spTrackEntryMap.find(nextPtr);
if (entry == _spTrackEntryMap.end())
{
_spTrackEntryMap.emplace(nextPtr, nextVal.get());
nextVal = sptrackentry_to_jsval(cx, *v.next);
}
else
{
nextVal.set(entry->second);
}
JS::RootedObject entry(cx, proxy->obj);
return OBJECT_TO_JSVAL(entry);
}
JS::RootedValue previousVal(cx);
if (v.previous)
else
{
auto previousPtr = v.previous;
auto entry = _spTrackEntryMap.find(previousPtr);
if (entry == _spTrackEntryMap.end())
{
_spTrackEntryMap.emplace(previousPtr, previousVal.get());
previousVal = sptrackentry_to_jsval(cx, *previousPtr);
}
else
{
previousVal.set(entry->second);
}
}
JS::RootedValue jsanimation(cx, spanimation_to_jsval(cx, *v.animation));
bool ok = JS_DefineProperty(cx, tmp, "delay", v.delay, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS::RootedObject tmp(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
if (!tmp) return JSVAL_NULL;
jsb_new_proxy(&v, tmp);
js_add_FinalizeHook(cx, tmp, false);
#if COCOS2D_DEBUG > 1
CCLOG("++++++WEAK_REF++++++ Cpp(spine::TrackEntry): %p - JS: %p", &v, tmp.get());
#endif // COCOS2D_DEBUG
JS::RootedValue jsanimation(cx, spanimation_to_jsval(cx, *v.animation));
bool ok = JS_DefineProperty(cx, tmp, "delay", v.delay, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "time", v.time, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "lastTime", v.lastTime, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "endTime", v.endTime, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
@ -325,15 +346,16 @@ jsval sptrackentry_to_jsval(JSContext* cx, spTrackEntry& v)
JS_DefineProperty(cx, tmp, "mixTime", v.mixTime, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "mixDuration", v.mixDuration, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "animation", jsanimation, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "next", nextVal, JSPROP_ENUMERATE | JSPROP_PERMANENT) &&
JS_DefineProperty(cx, tmp, "previous", previousVal, JSPROP_ENUMERATE | JSPROP_PERMANENT);
if (ok)
{
return OBJECT_TO_JSVAL(tmp);
JS_DefineProperty(cx, tmp, "next", JS::UndefinedHandleValue, JSPROP_ENUMERATE | JSPROP_PERMANENT, jsb_spine_TrackEntry_get_next) &&
JS_DefineProperty(cx, tmp, "previous", JS::UndefinedHandleValue, JSPROP_ENUMERATE | JSPROP_PERMANENT, jsb_spine_TrackEntry_get_previous);
if (ok)
{
return OBJECT_TO_JSVAL(tmp);
}
return JSVAL_NULL;
}
return JSVAL_NULL;
}
bool jsb_cocos2dx_spine_findBone(JSContext *cx, uint32_t argc, jsval *vp)
@ -481,7 +503,6 @@ bool jsb_cocos2dx_spine_getCurrent(JSContext *cx, uint32_t argc, jsval *vp)
if (ret)
{
jsret = sptrackentry_to_jsval(cx, *ret);
_spTrackEntryMap.clear();
}
} while (0);
@ -495,7 +516,6 @@ bool jsb_cocos2dx_spine_getCurrent(JSContext *cx, uint32_t argc, jsval *vp)
if (ret)
{
jsret = sptrackentry_to_jsval(cx, *ret);
_spTrackEntryMap.clear();
}
} while (0);
@ -532,7 +552,6 @@ bool jsb_cocos2dx_spine_setAnimation(JSContext *cx, uint32_t argc, jsval *vp)
if (ret)
{
jsret = sptrackentry_to_jsval(cx, *ret);
_spTrackEntryMap.clear();
}
} while(0);
@ -570,7 +589,6 @@ bool jsb_cocos2dx_spine_addAnimation(JSContext *cx, uint32_t argc, jsval *vp)
if (ret)
{
jsret = sptrackentry_to_jsval(cx, *ret);
_spTrackEntryMap.clear();
}
} while(0);
@ -596,7 +614,6 @@ bool jsb_cocos2dx_spine_addAnimation(JSContext *cx, uint32_t argc, jsval *vp)
if (ret)
{
jsret = sptrackentry_to_jsval(cx, *ret);
_spTrackEntryMap.clear();
}
} while(0);

View File

@ -38,7 +38,7 @@ ccui.Widget.prototype._ctor
= ccui.ScrollView.prototype._ctor
= function(){
this.init();
}
};
ccui.Button.prototype._ctor = function (normalImage, selectedImage, disableImage, texType) {
if(texType !== undefined)
@ -80,7 +80,7 @@ ccui.ImageView.prototype._ctor = function(imageFileName, texType){
}
else
ccui.Widget.prototype.init.call(this);
}
};
ccui.LoadingBar.prototype._ctor = function(textureName, percentage){
ccui.Widget.prototype.init.call(this);

View File

@ -737,35 +737,32 @@ cc.defineGetterSetter(cc.loader, "audioPath", function(){
cc.formatStr = function(){
var args = arguments;
var l = args.length;
if(l < 1)
return "";
if (l < 1) return '';
var REGEXP_NUM_OR_STR = /(%d)|(%s)/;
var i = 1;
var str = args[0];
var needToFormat = true;
if(typeof str === "object"){
needToFormat = false;
var hasSubstitution = typeof str === 'string' && REGEXP_NUM_OR_STR.test(str);
if (hasSubstitution) {
var REGEXP_STR = /%s/;
for (; i < l; ++i) {
var arg = args[i];
var regExpToTest = typeof arg === 'number' ? REGEXP_NUM_OR_STR : REGEXP_STR;
if (regExpToTest.test(str))
str = str.replace(regExpToTest, arg);
else
str += ' ' + arg;
}
}
for(var i = 1; i < l; ++i){
var arg = args[i];
if(needToFormat){
while(true){
var result = null;
if(typeof arg === "number"){
result = str.match(/(%d)|(%s)/);
if(result){
str = str.replace(/(%d)|(%s)/, arg);
break;
}
}
result = str.match(/%s/);
if(result)
str = str.replace(/%s/, arg);
else
str += " " + arg;
break;
else {
if (l > 1) {
for (; i < l; ++i) {
str += ' ' + args[i];
}
}else
str += " " + arg;
}
else {
str = '' + str;
}
}
return str;
};

View File

@ -26,7 +26,7 @@
// CCConfig.js
//
cc.ENGINE_VERSION = "Cocos2d-JS v3.13";
cc.ENGINE_VERSION = "Cocos2d-JS v3.14";
cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL = 0;
cc.DIRECTOR_STATS_POSITION = {x: 0, y: 0};

View File

@ -214,7 +214,7 @@ bool ControlSwitchSprite::initWithMaskSprite(
return false;
}
void ControlSwitchSprite::updateTweenAction(float value, const std::string& /*key*/)
void ControlSwitchSprite::updateTweenAction(float value, const std::string& key)
{
CCLOGINFO("key = %s, value = %f", key.c_str(), value);
setSliderXPosition(value);

2
web

@ -1 +1 @@
Subproject commit 640431814638f732a4b886182820cc8a88a75e87
Subproject commit e5fe5bbf4f8e1016d58c56ee7079f38f38b2bfb1