Use JS::Heap instead of Mozilla::maybe to improve stability

This commit is contained in:
pandamicro 2016-01-28 01:03:13 +08:00
parent 55756cb043
commit 554523a201
11 changed files with 336 additions and 276 deletions

View File

@ -35,19 +35,21 @@ public:
JSB_HeapValueWrapper(JSContext* cx, JS::HandleValue value)
:_cx(cx)
{
_data.construct(cx, value);
_data = value;
js_add_object_root(value);
}
~JSB_HeapValueWrapper(){
_data.destroyIfConstructed();
JS::RootedValue value(_cx, _data);
js_remove_object_root(value);
}
jsval get(){
return _data.ref();
return _data;
}
private:
JSContext* _cx;
mozilla::Maybe<JS::PersistentRootedValue> _data;
JS::Heap<JS::Value> _data;
};
static bool js_cocos2dx_Sprite3D_createAsync(JSContext *cx, uint32_t argc, jsval *vp)
@ -59,15 +61,18 @@ static bool js_cocos2dx_Sprite3D_createAsync(JSContext *cx, uint32_t argc, jsval
jsval_to_std_string(cx, args.get(0), &modelPath);
std::function<void(Sprite3D*, void*)> callback;
JS::RootedObject cb(cx, args.get(argc == 4 ? 2 : 3).toObjectOrNull());
std::shared_ptr<JSFunctionWrapper> func(new JSFunctionWrapper(cx, cb, args.get(argc == 4 ? 1 : 2)));
JS::RootedValue targetVal(cx, args.get(argc == 4 ? 2 : 3));
JS::RootedObject target(cx, targetVal.toObjectOrNull());
JS::RootedValue fval(cx, args.get(argc == 4 ? 1 : 2));
std::shared_ptr<JSFunctionWrapper> func(new JSFunctionWrapper(cx, target, fval));
auto lambda = [=](Sprite3D* larg0, void* larg1) -> void{
jsval largv[2];
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
largv[0] = OBJECT_TO_JSVAL(js_get_or_create_jsobject<Sprite3D>(cx, larg0));
JSB_HeapValueWrapper* v = (JSB_HeapValueWrapper*)larg1;
largv[1] = JS::RootedValue(cx, v->get());
JS::RootedValue dataVal(cx, v->get());
largv[1] = dataVal;
JS::RootedValue rval(cx);
bool ok = func->invoke(2, largv, &rval);

View File

@ -159,12 +159,12 @@ bool JSB_CCPhysicsDebugNode_debugNodeForCPSpace__static(JSContext *cx, uint32_t
JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
PhysicsDebugNode* ret = PhysicsDebugNode::create(arg0);
jsval jsret;
JS::RootedValue jsret(cx);
if (ret) {
js_type_class_t *typeClass = js_get_type_from_native<PhysicsDebugNode>(ret);
JS::RootedValue jsret(cx, OBJECT_TO_JSVAL(jsb_ref_autoreleased_get_or_create_jsobject(cx, ret, typeClass, "cocos2d::extension::PhysicsDebugNode")));
jsret.set(OBJECT_TO_JSVAL(jsb_ref_autoreleased_get_or_create_jsobject(cx, ret, typeClass, "cocos2d::extension::PhysicsDebugNode")));
} else {
jsret = JSVAL_NULL;
jsret.set(JS::NullValue());
}
args.rval().set(jsret);
@ -321,12 +321,12 @@ bool JSPROXY_CCPhysicsSprite_spriteWithSpriteFrame__static(JSContext *cx, uint32
}
PhysicsSprite* ret = PhysicsSprite::createWithSpriteFrame(arg0);
jsval jsret;
JS::RootedValue jsret(cx);
if (ret) {
js_type_class_t *typeClass = js_get_type_from_native<PhysicsSprite>(ret);
JS::RootedValue jsret(cx, OBJECT_TO_JSVAL(jsb_ref_autoreleased_get_or_create_jsobject(cx, ret, typeClass, "cocos2d::extension::PhysicsSprite")));
jsret.set(OBJECT_TO_JSVAL(jsb_ref_autoreleased_get_or_create_jsobject(cx, ret, typeClass, "cocos2d::extension::PhysicsSprite")));
} else {
jsret = JSVAL_NULL;
jsret.set(JS::NullValue());
}
args.rval().set(jsret);
return true;
@ -619,11 +619,11 @@ struct collision_handler {
cpCollisionType typeA;
cpCollisionType typeB;
mozilla::Maybe<JS::RootedObject> begin;
mozilla::Maybe<JS::RootedObject> pre;
mozilla::Maybe<JS::RootedObject> post;
mozilla::Maybe<JS::RootedObject> separate;
mozilla::Maybe<JS::RootedObject> jsthis;
JS::Heap<JSObject*> begin;
JS::Heap<JSObject*> pre;
JS::Heap<JSObject*> post;
JS::Heap<JSObject*> separate;
JS::Heap<JSObject*> jsthis;
JSContext *cx;
// "owner" of the collision handler
@ -637,36 +637,35 @@ struct collision_handler {
collision_handler()
{
JSContext *globalcx = ScriptingCore::getInstance()->getGlobalContext();
begin.construct(globalcx);
pre.construct(globalcx);
post.construct(globalcx);
separate.construct(globalcx);
jsthis.construct(globalcx);
begin = nullptr;
pre = nullptr;
post = nullptr;
separate = nullptr;
jsthis = nullptr;
}
void setJSSpace(JS::HandleValue jsspace)
{
if (!jsspace.isNullOrUndefined())
{
jsthis.ref() = jsspace.toObjectOrNull();
jsthis = jsspace.toObjectOrNull();
JS::RootedValue callback(ScriptingCore::getInstance()->getGlobalContext());
callback.set(OBJECT_TO_JSVAL(begin.ref()));
callback.set(OBJECT_TO_JSVAL(begin));
if (!callback.isNullOrUndefined())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(pre.ref()));
callback.set(OBJECT_TO_JSVAL(pre));
if (!callback.isNullOrUndefined())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(post.ref()));
callback.set(OBJECT_TO_JSVAL(post));
if (!callback.isNullOrUndefined())
{
js_add_object_reference(jsspace, callback);
}
callback.set(OBJECT_TO_JSVAL(separate.ref()));
callback.set(OBJECT_TO_JSVAL(separate));
if (!callback.isNullOrUndefined())
{
js_add_object_reference(jsspace, callback);
@ -706,8 +705,8 @@ static cpBool myCollisionBegin(cpArbiter *arb, cpSpace *space, void *data)
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue rval(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis.ref());
JS::RootedValue jsbegin(handler->cx, OBJECT_TO_JSVAL(handler->begin.ref()));
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jsbegin(handler->cx, OBJECT_TO_JSVAL(handler->begin));
bool ok = JS_CallFunctionValue(handler->cx, jsthis, jsbegin, JS::HandleValueArray::fromMarkedLocation(2, args), &rval);
JSB_PRECONDITION2(ok, handler->cx, cpFalse, "Error calling collision callback: begin");
@ -736,8 +735,8 @@ static cpBool myCollisionPre(cpArbiter *arb, cpSpace *space, void *data)
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue rval(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis.ref());
JS::RootedValue jspre(handler->cx, OBJECT_TO_JSVAL(handler->pre.ref()));
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jspre(handler->cx, OBJECT_TO_JSVAL(handler->pre));
bool ok = JS_CallFunctionValue( handler->cx, jsthis, jspre, JS::HandleValueArray::fromMarkedLocation(2, args), &rval);
JSB_PRECONDITION2(ok, handler->cx, false, "Error calling collision callback: pre");
@ -767,8 +766,8 @@ static void myCollisionPost(cpArbiter *arb, cpSpace *space, void *data)
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue ignore(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis.ref());
JS::RootedValue jspost(handler->cx, OBJECT_TO_JSVAL(handler->post.ref()));
JS::RootedObject jsthis(handler->cx, handler->jsthis);
JS::RootedValue jspost(handler->cx, OBJECT_TO_JSVAL(handler->post));
bool ok = JS_CallFunctionValue( handler->cx, jsthis, jspost, JS::HandleValueArray::fromMarkedLocation(2, args), &ignore);
JSB_PRECONDITION2(ok, handler->cx, , "Error calling collision callback: Post");
}
@ -793,8 +792,8 @@ static void myCollisionSeparate(cpArbiter *arb, cpSpace *space, void *data)
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue ignore(handler->cx);
JS::RootedObject jsthis(handler->cx, handler->jsthis.ref());
JS::RootedValue jssep(handler->cx, OBJECT_TO_JSVAL(handler->separate.ref()));
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");}
@ -850,13 +849,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.ref() = argvp->toObjectOrNull();
handler->begin = argvp->toObjectOrNull();
argvp++;
handler->pre.ref() = argvp->toObjectOrNull();
handler->pre = argvp->toObjectOrNull();
argvp++;
handler->post.ref() = argvp->toObjectOrNull();
handler->post = argvp->toObjectOrNull();
argvp++;
handler->separate.ref() = argvp->toObjectOrNull();
handler->separate = argvp->toObjectOrNull();
argvp++;
JS::RootedValue spaceVal(cx, OBJECT_TO_JSVAL(jsspace));
@ -871,10 +870,10 @@ bool __jsb_cpSpace_addCollisionHandler(JSContext *cx, jsval *vp, jsval *argvp, J
handler->cx = cx;
cpSpaceAddCollisionHandler(space, handler->typeA, handler->typeB,
!handler->begin.ref() ? NULL : &myCollisionBegin,
!handler->pre.ref() ? NULL : &myCollisionPre,
!handler->post.ref() ? NULL : &myCollisionPost,
!handler->separate.ref() ? NULL : &myCollisionSeparate,
!handler->begin ? NULL : &myCollisionBegin,
!handler->pre ? NULL : &myCollisionPre,
!handler->post ? NULL : &myCollisionPost,
!handler->separate ? NULL : &myCollisionSeparate,
handler );
@ -941,10 +940,10 @@ bool JSB_cpSpace_setDefaultCollisionHandler(JSContext *cx, uint32_t argc, jsval
handler->typeA = 0;
handler->typeB = 0;
handler->begin.ref() = args.get(0).toObjectOrNull();
handler->pre.ref() = args.get(1).toObjectOrNull();
handler->post.ref() = args.get(2).toObjectOrNull();
handler->separate.ref() = args.get(3).toObjectOrNull();
handler->begin = args.get(0).toObjectOrNull();
handler->pre = args.get(1).toObjectOrNull();
handler->post = args.get(2).toObjectOrNull();
handler->separate = args.get(3).toObjectOrNull();
JS::RootedValue spaceVal(cx, OBJECT_TO_JSVAL(jsthis));
handler->setJSSpace(spaceVal);
@ -956,10 +955,10 @@ bool JSB_cpSpace_setDefaultCollisionHandler(JSContext *cx, uint32_t argc, jsval
handler->cx = cx;
cpSpaceSetDefaultCollisionHandler(space,
!handler->begin.ref() ? NULL : &myCollisionBegin,
!handler->pre.ref() ? NULL : &myCollisionPre,
!handler->post.ref() ? NULL : &myCollisionPost,
!handler->separate.ref() ? NULL : &myCollisionSeparate,
!handler->begin ? NULL : &myCollisionBegin,
!handler->pre ? NULL : &myCollisionPre,
!handler->post ? NULL : &myCollisionPost,
!handler->separate ? NULL : &myCollisionSeparate,
handler );
//

View File

@ -40,20 +40,21 @@ JSTouchDelegate::JSTouchDelegate()
: _touchListenerAllAtOnce(nullptr)
, _touchListenerOneByOne(nullptr)
{
auto cx = ScriptingCore::getInstance()->getGlobalContext();
_obj.construct(cx);
_obj = nullptr;
}
JSTouchDelegate::~JSTouchDelegate()
{
CCLOGINFO("In the destructor of JSTouchDelegate.");
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue objVal(cx, OBJECT_TO_JSVAL(_obj.ref()));
if (!objVal.isNullOrUndefined())
if (_obj)
{
js_remove_object_root(objVal);
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue objVal(cx, OBJECT_TO_JSVAL(_obj));
if (!objVal.isNullOrUndefined())
{
js_remove_object_root(objVal);
}
}
_obj.destroyIfConstructed();
}
void JSTouchDelegate::setDelegateForJSObject(JSObject* pJSObj, JSTouchDelegate* pDelegate)
@ -84,13 +85,17 @@ void JSTouchDelegate::removeDelegateForJSObject(JSObject* pJSObj)
void JSTouchDelegate::setJSObject(JS::HandleObject obj)
{
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue objVal(cx, OBJECT_TO_JSVAL(_obj.ref()));
if (!objVal.isNullOrUndefined())
JS::RootedValue objVal(cx);
if (_obj)
{
js_remove_object_root(objVal);
objVal.set(OBJECT_TO_JSVAL(_obj));
if (!objVal.isNullOrUndefined())
{
js_remove_object_root(objVal);
}
}
_obj.ref() = obj;
_obj = obj;
objVal.set(OBJECT_TO_JSVAL(obj));
if (!objVal.isNullOrUndefined())
@ -149,7 +154,8 @@ bool JSTouchDelegate::onTouchBegan(Touch *touch, Event *event)
JS::RootedValue retval(cx);
bool bRet = false;
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::BEGAN, touch, _obj.ref(), &retval);
JS::RootedObject obj(cx, _obj);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::BEGAN, touch, obj, &retval);
if(retval.isBoolean())
{
@ -163,46 +169,51 @@ bool JSTouchDelegate::onTouchBegan(Touch *touch, Event *event)
void JSTouchDelegate::onTouchMoved(Touch *touch, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::MOVED, touch, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::MOVED, touch, obj);
}
void JSTouchDelegate::onTouchEnded(Touch *touch, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::ENDED, touch, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::ENDED, touch, obj);
}
void JSTouchDelegate::onTouchCancelled(Touch *touch, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::CANCELLED, touch, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchEvent(EventTouch::EventCode::CANCELLED, touch, obj);
}
// optional
void JSTouchDelegate::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::BEGAN, touches, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::BEGAN, touches, obj);
}
void JSTouchDelegate::onTouchesMoved(const std::vector<Touch*>& touches, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::MOVED, touches, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::MOVED, touches, obj);
}
void JSTouchDelegate::onTouchesEnded(const std::vector<Touch*>& touches, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::ENDED, touches, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::ENDED, touches, obj);
}
void JSTouchDelegate::onTouchesCancelled(const std::vector<Touch*>& touches, Event *event)
{
CC_UNUSED_PARAM(event);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::CANCELLED, touches, _obj.ref());
JS::RootedObject obj(ScriptingCore::getInstance()->getGlobalContext(), _obj);
ScriptingCore::getInstance()->executeCustomTouchesEvent(EventTouch::EventCode::CANCELLED, touches, obj);
}
// cc.EventTouch#getTouches
@ -538,6 +549,7 @@ void js_add_FinalizeHook(JSContext *cx, JS::HandleObject target)
JS::RootedObject proto(cx, jsb_FinalizeHook_prototype);
JS::RootedObject hook(cx, JS_NewObject(cx, jsb_FinalizeHook_class, proto, JS::NullPtr()));
jsb_register_finalize_hook(hook.get(), target.get());
CCLOG("======= %p", hook.get());
JS::RootedValue hookVal(cx, OBJECT_TO_JSVAL(hook));
JS_SetProperty(cx, target, "__hook", hookVal);
}
@ -678,111 +690,116 @@ void js_remove_object_root(JS::HandleValue target)
JSCallbackWrapper::JSCallbackWrapper()
{
ScriptingCore *engine = ScriptingCore::getInstance();
JSContext* cx = engine->getGlobalContext();
_jsCallback.construct(cx, JS::NullHandleValue);
_jsThisObj.construct(cx, JS::NullHandleValue);
_extraData.construct(cx, JS::NullHandleValue);
_owner.construct(cx, JS::NullHandleValue);
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_jsCallback = JS::NullValue();
_jsThisObj = JS::NullValue();
_extraData = JS::NullValue();
JS::RootedObject root(cx);
get_or_create_js_obj("jsb._root", &root);
JS::RootedValue valRoot(cx, OBJECT_TO_JSVAL(root));
_owner.ref() = valRoot;
_owner = valRoot;
}
JSCallbackWrapper::JSCallbackWrapper(JS::HandleValue owner)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_owner.construct(cx, JS::NullHandleValue);
_owner.ref() = owner;
_jsCallback.construct(cx, JS::NullHandleValue);
_jsThisObj.construct(cx, JS::NullHandleValue);
_extraData.construct(cx, JS::NullHandleValue);
_owner = owner;
_jsCallback = JS::NullValue();
_jsThisObj = JS::NullValue();
_extraData = JS::NullValue();
}
JSCallbackWrapper::~JSCallbackWrapper()
{
if (!_owner.ref().isNullOrUndefined())
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
if (!_jsCallback.ref().isNullOrUndefined())
JS::RootedValue target(cx, _jsCallback);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _jsCallback.ref());
js_remove_object_reference(ownerVal, target);
}
if (!_jsThisObj.ref().isNullOrUndefined())
target.set(_jsThisObj);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _jsThisObj.ref());
js_remove_object_reference(ownerVal, target);
}
if (!_extraData.ref().isNullOrUndefined())
target.set(_extraData);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _extraData.ref());
js_remove_object_reference(ownerVal, target);
}
}
_owner.destroyIfConstructed();
_jsCallback.destroyIfConstructed();
_jsThisObj.destroyIfConstructed();
_extraData.destroyIfConstructed();
}
void JSCallbackWrapper::setJSCallbackFunc(JS::HandleValue func) {
if (!_owner.ref().isNullOrUndefined())
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
if (!_jsCallback.ref().isNullOrUndefined())
JS::RootedValue target(cx, _jsCallback);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _jsCallback.ref());
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(_owner.ref(), func);
js_add_object_reference(ownerVal, func);
}
if (!func.isNullOrUndefined())
{
_jsCallback.ref() = func;
_jsCallback = func;
}
}
void JSCallbackWrapper::setJSCallbackThis(JS::HandleValue thisObj) {
if (!_owner.ref().isNullOrUndefined())
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
if (!_jsThisObj.ref().isNullOrUndefined())
JS::RootedValue target(cx, _jsThisObj);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _jsThisObj.ref());
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(_owner.ref(), thisObj);
js_add_object_reference(ownerVal, thisObj);
}
if (!thisObj.isNullOrUndefined())
{
_jsThisObj.ref() = thisObj;
_jsThisObj = thisObj;
}
}
void JSCallbackWrapper::setJSExtraData(JS::HandleValue data) {
if (!_owner.ref().isNullOrUndefined())
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
if (!_extraData.ref().isNullOrUndefined())
JS::RootedValue target(cx, _extraData);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _extraData.ref());
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(_owner.ref(), data);
js_add_object_reference(ownerVal, data);
}
if (!data.isNullOrUndefined())
{
_extraData.ref() = data;
_extraData = data;
}
}
const jsval JSCallbackWrapper::getJSCallbackFunc() const
{
return _jsCallback.ref().get();
return _jsCallback;
}
const jsval JSCallbackWrapper::getJSCallbackThis() const
{
return _jsThisObj.ref().get();
return _jsThisObj;
}
const jsval JSCallbackWrapper::getJSExtraData() const
{
return _extraData.ref().get();
return _extraData;
}
// cc.CallFunc.create( func, this, [data])
@ -923,8 +940,7 @@ JSScheduleWrapper::JSScheduleWrapper()
, _priority(0)
, _isUpdateSchedule(false)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_pPureJSTarget.construct(cx);
_pPureJSTarget = nullptr;
}
JSScheduleWrapper::JSScheduleWrapper(JS::HandleValue owner)
@ -933,13 +949,7 @@ JSScheduleWrapper::JSScheduleWrapper(JS::HandleValue owner)
, _priority(0)
, _isUpdateSchedule(false)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_pPureJSTarget.construct(cx);
}
JSScheduleWrapper::~JSScheduleWrapper()
{
_pPureJSTarget.destroyIfConstructed();
_pPureJSTarget = nullptr;
}
void JSScheduleWrapper::setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target) {
@ -1260,12 +1270,12 @@ void JSScheduleWrapper::setTarget(Ref* pTarget)
void JSScheduleWrapper::setPureJSTarget(JS::HandleObject pPureJSTarget)
{
_pPureJSTarget.ref() = pPureJSTarget;
_pPureJSTarget = pPureJSTarget;
}
JSObject* JSScheduleWrapper::getPureJSTarget()
{
return _pPureJSTarget.ref().get();
return _pPureJSTarget;
}
void JSScheduleWrapper::setPriority(int priority)

View File

@ -138,10 +138,10 @@ public:
const jsval getJSCallbackThis() const;
const jsval getJSExtraData() const;
protected:
mozilla::Maybe<JS::RootedValue> _owner;
mozilla::Maybe<JS::RootedValue> _jsCallback;
mozilla::Maybe<JS::RootedValue> _jsThisObj;
mozilla::Maybe<JS::RootedValue> _extraData;
JS::Heap<JS::Value> _owner;
JS::Heap<JS::Value> _jsCallback;
JS::Heap<JS::Value> _jsThisObj;
JS::Heap<JS::Value> _extraData;
};
@ -150,7 +150,6 @@ class JSScheduleWrapper: public JSCallbackWrapper {
public:
JSScheduleWrapper();
JSScheduleWrapper(JS::HandleValue owner);
virtual ~JSScheduleWrapper();
static void setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target);
static cocos2d::__Array * getTargetForSchedule(JS::HandleValue sched);
@ -186,7 +185,7 @@ public:
protected:
Ref* _pTarget;
mozilla::Maybe<JS::RootedObject> _pPureJSTarget;
JS::Heap<JSObject*> _pPureJSTarget;
int _priority;
bool _isUpdateSchedule;
};
@ -225,7 +224,7 @@ public:
void onTouchesCancelled(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event *event);
private:
mozilla::Maybe<JS::RootedObject> _obj;
JS::Heap<JSObject*> _obj;
typedef std::unordered_map<JSObject*, JSTouchDelegate*> TouchDelegateMap;
typedef std::pair<JSObject*, JSTouchDelegate*> TouchDelegatePair;
static TouchDelegateMap sTouchDelegateMap;

View File

@ -39,13 +39,7 @@ class JSB_ScrollViewDelegate
public:
JSB_ScrollViewDelegate()
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_JSDelegate.construct(cx);
}
virtual ~JSB_ScrollViewDelegate()
{
_JSDelegate.destroyIfConstructed();
_JSDelegate = nullptr;
}
virtual void scrollViewDidScroll(ScrollView* view) override
@ -54,7 +48,7 @@ public:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate.ref()), "scrollViewDidScroll", 1, &arg);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate), "scrollViewDidScroll", 1, &arg);
}
virtual void scrollViewDidZoom(ScrollView* view) override
@ -63,15 +57,15 @@ public:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate.ref()), "scrollViewDidZoom", 1, &arg);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate), "scrollViewDidZoom", 1, &arg);
}
void setJSDelegate(JS::HandleObject pJSDelegate)
{
_JSDelegate.ref() = pJSDelegate;
_JSDelegate = pJSDelegate;
}
private:
mozilla::Maybe<JS::RootedObject> _JSDelegate;
JS::Heap<JSObject*> _JSDelegate;
};
static bool js_cocos2dx_CCScrollView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)
@ -114,13 +108,7 @@ class JSB_TableViewDelegate
public:
JSB_TableViewDelegate()
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_JSDelegate.construct(cx);
}
virtual ~JSB_TableViewDelegate()
{
_JSDelegate.destroyIfConstructed();
_JSDelegate = nullptr;
}
virtual void scrollViewDidScroll(ScrollView* view) override
@ -155,7 +143,7 @@ public:
void setJSDelegate(JS::HandleObject pJSDelegate)
{
_JSDelegate.ref() = pJSDelegate;
_JSDelegate = pJSDelegate;
}
private:
@ -165,7 +153,7 @@ private:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate.ref()), jsFunctionName.c_str(), 1, &arg);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate), jsFunctionName.c_str(), 1, &arg);
}
void callJSDelegate(TableView* table, TableViewCell* cell, std::string jsFunctionName)
@ -180,10 +168,10 @@ private:
args[0] = OBJECT_TO_JSVAL(p->obj);
args[1] = OBJECT_TO_JSVAL(pCellProxy->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate.ref()), jsFunctionName.c_str(), 2, args);
ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(_JSDelegate), jsFunctionName.c_str(), 2, args);
}
mozilla::Maybe<JS::RootedObject> _JSDelegate;
JS::Heap<JSObject*> _JSDelegate;
};
static bool js_cocos2dx_CCTableView_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)
@ -231,13 +219,7 @@ class JSB_TableViewDataSource
public:
JSB_TableViewDataSource()
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_JSTableViewDataSource.construct(cx);
}
virtual ~JSB_TableViewDataSource()
{
_JSTableViewDataSource.destroyIfConstructed();
_JSTableViewDataSource = nullptr;
}
virtual Size tableCellSizeForIndex(TableView *table, ssize_t idx) override
@ -297,7 +279,7 @@ public:
void setTableViewDataSource(JS::HandleObject pJSSource)
{
_JSTableViewDataSource.ref() = pJSSource;
_JSTableViewDataSource = pJSSource;
}
private:
@ -312,7 +294,7 @@ private:
JS::RootedValue temp_retval(cx);
jsval dataVal = OBJECT_TO_JSVAL(p->obj);
JS::RootedObject obj(cx, _JSTableViewDataSource.ref());
JS::RootedObject obj(cx, _JSTableViewDataSource);
JSAutoCompartment ac(cx, obj);
if (JS_HasProperty(cx, obj, jsFunctionName.c_str(), &hasAction) && hasAction)
@ -345,7 +327,7 @@ private:
dataVal[0] = OBJECT_TO_JSVAL(p->obj);
dataVal[1] = ssize_to_jsval(cx,idx);
JS::RootedObject obj(cx, _JSTableViewDataSource.ref());
JS::RootedObject obj(cx, _JSTableViewDataSource);
JSAutoCompartment ac(cx, obj);
if (JS_HasProperty(cx, obj, jsFunctionName.c_str(), &hasAction) && hasAction)
@ -368,7 +350,7 @@ private:
}
private:
mozilla::Maybe<JS::RootedObject> _JSTableViewDataSource;
JS::Heap<JSObject*> _JSTableViewDataSource;
};
static bool js_cocos2dx_CCTableView_setDataSource(JSContext *cx, uint32_t argc, jsval *vp)
@ -541,14 +523,12 @@ public:
: _callback(nullptr),
_type(Control::EventType::TOUCH_DOWN)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_jsFunc.construct(cx);
_jsFunc = nullptr;
}
virtual ~JSB_ControlButtonTarget()
{
CCLOGINFO("In the destruction of JSB_ControlButtonTarget ...");
_jsFunc.destroyIfConstructed();
if (_callback != nullptr)
{
@ -593,7 +573,7 @@ public:
}
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_callback = new (std::nothrow) JSFunctionWrapper(cx, jsTarget, jsFunc);
_jsFunc.ref() = jsFunc.toObjectOrNull();
_jsFunc = jsFunc.toObjectOrNull();
}
void setEventType(Control::EventType type)
@ -605,7 +585,7 @@ public:
static std::multimap<JSObject*, JSB_ControlButtonTarget*> _jsNativeTargetMap;
JSFunctionWrapper *_callback;
Control::EventType _type;
mozilla::Maybe<JS::RootedObject> _jsFunc;
JS::Heap<JSObject*> _jsFunc;
};
std::multimap<JSObject*, JSB_ControlButtonTarget*> JSB_ControlButtonTarget::_jsNativeTargetMap;
@ -631,7 +611,7 @@ static bool js_cocos2dx_CCControl_addTargetWithActionForControlEvents(JSContext
auto range = JSB_ControlButtonTarget::_jsNativeTargetMap.equal_range(jsDelegate);
for (auto it = range.first; it != range.second; ++it)
{
if (it->second->_jsFunc.ref().get() == jsFunc && arg2 == it->second->_type)
if (it->second->_jsFunc.get() == jsFunc && arg2 == it->second->_type)
{
// Return true directly.
args.rval().setUndefined();
@ -695,7 +675,7 @@ static bool js_cocos2dx_CCControl_removeTargetWithActionForControlEvents(JSConte
auto range = JSB_ControlButtonTarget::_jsNativeTargetMap.equal_range(obj);
for (auto it = range.first; it != range.second; ++it)
{
if (it->second->_jsFunc.ref().get() == jsFunc && arg2 == it->second->_type)
if (it->second->_jsFunc.get() == jsFunc && arg2 == it->second->_type)
{
nativeTargetToRemoved = it->second;
JSB_ControlButtonTarget::_jsNativeTargetMap.erase(it);
@ -842,8 +822,8 @@ __JSDownloaderDelegator::__JSDownloaderDelegator(JSContext *cx, JS::HandleObject
: _cx(cx)
, _url(url)
{
_obj.construct(_cx, obj);
_jsCallback.construct(_cx, callback);
_obj = obj;
_jsCallback = callback;
JS::RootedValue target(cx, OBJECT_TO_JSVAL(obj));
if (!target.isNullOrUndefined())
@ -859,19 +839,17 @@ __JSDownloaderDelegator::__JSDownloaderDelegator(JSContext *cx, JS::HandleObject
__JSDownloaderDelegator::~__JSDownloaderDelegator()
{
JS::RootedValue target(_cx, OBJECT_TO_JSVAL(_obj.ref()));
JS::RootedValue target(_cx, OBJECT_TO_JSVAL(_obj));
if (!target.isNullOrUndefined())
{
js_remove_object_root(target);
}
target.set(OBJECT_TO_JSVAL(_jsCallback.ref()));
target.set(OBJECT_TO_JSVAL(_jsCallback));
if (!target.isNullOrUndefined())
{
js_remove_object_root(target);
}
_obj.destroyIfConstructed();
_jsCallback.destroyIfConstructed();
_downloader->onTaskError = (nullptr);
_downloader->onDataTaskSuccess = (nullptr);
}
@ -948,7 +926,7 @@ void __JSDownloaderDelegator::onError()
{
Director::getInstance()->getScheduler()->performFunctionInCocosThread([this]
{
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback.ref()));
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback));
if (!callback.isNull()) {
JS::RootedObject global(_cx, ScriptingCore::getInstance()->getGlobalObject());
JSAutoCompartment ac(_cx, global);
@ -982,7 +960,7 @@ void __JSDownloaderDelegator::onSuccess(Texture2D *tex)
valArr[1] = JSVAL_NULL;
}
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback.ref()));
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback));
if (!callback.isNull())
{
JS::RootedValue retval(_cx);

View File

@ -26,7 +26,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/Maybe.h"
#include "cocos/network/CCDownloader.h"
#include "renderer/CCTexture2D.h"
@ -50,8 +49,8 @@ private:
std::shared_ptr<cocos2d::network::Downloader> _downloader;
std::string _url;
JSContext *_cx;
mozilla::Maybe<JS::RootedObject> _jsCallback;
mozilla::Maybe<JS::RootedObject> _obj;
JS::Heap<JSObject*> _jsCallback;
JS::Heap<JSObject*> _obj;
};
void register_all_cocos2dx_extension_manual(JSContext* cx, JS::HandleObject global);

View File

@ -87,71 +87,74 @@ const char* JSStringWrapper::get()
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval)
: _cx(cx)
{
_jsthis.construct(cx, jsthis);
_fval.construct(cx, fval);
_owner.construct(cx, JS::NullHandleValue);
_jsthis = jsthis;
_fval = fval;
JS::RootedObject root(cx);
get_or_create_js_obj("jsb._root", &root);
JS::RootedValue valRoot(cx, OBJECT_TO_JSVAL(root));
_owner.ref() = valRoot;
_owner = valRoot;
if (!valRoot.isNullOrUndefined())
{
JS::RootedValue thisVal(cx, OBJECT_TO_JSVAL(_jsthis.ref()));
JS::RootedValue thisVal(cx, OBJECT_TO_JSVAL(_jsthis));
if (!thisVal.isNullOrUndefined())
{
js_add_object_reference(valRoot, thisVal);
}
if (!_fval.ref().isNullOrUndefined())
JS::RootedValue funcVal(cx, _fval);
if (!funcVal.isNullOrUndefined())
{
js_add_object_reference(valRoot, _fval.ref());
js_add_object_reference(valRoot, funcVal);
}
}
}
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval, JS::HandleValue owner)
: _cx(cx)
{
_jsthis.construct(cx, jsthis);
_fval.construct(cx, fval);
_owner.construct(cx, owner);
_jsthis = jsthis;
_fval = fval;
_owner = owner;
JS::RootedValue ownerVal(cx, owner);
JS::RootedValue thisVal(cx, OBJECT_TO_JSVAL(_jsthis.ref()));
JS::RootedValue thisVal(cx, OBJECT_TO_JSVAL(jsthis));
if (!thisVal.isNullOrUndefined())
{
js_add_object_reference(owner, thisVal);
js_add_object_reference(ownerVal, thisVal);
}
if (!_fval.ref().isNullOrUndefined())
JS::RootedValue funcVal(cx, _fval);
if (!funcVal.isNullOrUndefined())
{
js_add_object_reference(owner, _fval.ref());
js_add_object_reference(ownerVal, funcVal);
}
}
JSFunctionWrapper::~JSFunctionWrapper()
{
if (!_owner.ref().isNullOrUndefined())
JS::RootedValue ownerVal(_cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
JS::RootedValue thisVal(_cx, OBJECT_TO_JSVAL(_jsthis.ref()));
JS::RootedValue thisVal(_cx, OBJECT_TO_JSVAL(_jsthis));
if (!thisVal.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), thisVal);
js_remove_object_reference(ownerVal, thisVal);
}
if (!_fval.ref().isNullOrUndefined())
JS::RootedValue funcVal(_cx, _fval);
if (!funcVal.isNullOrUndefined())
{
js_remove_object_reference(_owner.ref(), _fval.ref());
js_remove_object_reference(ownerVal, funcVal);
}
}
_jsthis.destroyIfConstructed();
_fval.destroyIfConstructed();
_owner.destroyIfConstructed();
}
bool JSFunctionWrapper::invoke(unsigned int argc, jsval *argv, JS::MutableHandleValue rval)
{
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
return JS_CallFunctionValue(_cx, _jsthis.ref(), _fval.ref(), JS::HandleValueArray::fromMarkedLocation(argc, argv), rval);
JS::RootedObject thisObj(_cx, _jsthis);
JS::RootedValue fval(_cx, _fval);
return JS_CallFunctionValue(_cx, thisObj, fval, JS::HandleValueArray::fromMarkedLocation(argc, argv), rval);
}
static Color3B getColorFromJSObject(JSContext *cx, JS::HandleObject colorObject)

View File

@ -32,7 +32,6 @@
#include "cocos2d.h"
#include "spidermonkey_specifics.h"
#include "js-BindingsExport.h"
#include "mozilla/Maybe.h"
#define JSB_COMPATIBLE_WITH_COCOS2D_HTML5_BASIC_TYPES
@ -71,9 +70,9 @@ public:
bool invoke(unsigned int argc, jsval *argv, JS::MutableHandleValue rval);
private:
JSContext *_cx;
mozilla::Maybe<JS::RootedObject> _jsthis;
mozilla::Maybe<JS::RootedValue> _fval;
mozilla::Maybe<JS::RootedValue> _owner;
JS::Heap<JSObject*> _jsthis;
JS::Heap<JS::Value> _fval;
JS::Heap<JS::Value> _owner;
private:
CC_DISALLOW_COPY_AND_ASSIGN(JSFunctionWrapper);
};

View File

@ -215,8 +215,17 @@ void MinXmlHttpRequest::handle_requestResponse(cocos2d::network::HttpClient *sen
_errorFlag = true;
_status = 0;
_statusText.clear();
_notify(_onerrorCallback.ref());
_notify(_onloadendCallback.ref());
JS::RootedObject callback(_cx);
if (_onerrorCallback)
{
callback.set(_onerrorCallback);
_notify(callback);
}
if (_onloadendCallback)
{
callback.set(_onloadendCallback);
_notify(callback);
}
return;
}
}
@ -244,9 +253,22 @@ void MinXmlHttpRequest::handle_requestResponse(cocos2d::network::HttpClient *sen
_data[_dataSize] = '\0';
memcpy((void*)_data, (const void*)buffer->data(), _dataSize);
_notify(_onreadystateCallback.ref());
_notify(_onloadCallback.ref());
_notify(_onloadendCallback.ref());
JS::RootedObject callback(_cx);
if (_onreadystateCallback)
{
callback.set(_onreadystateCallback);
_notify(callback);
}
if (_onloadCallback)
{
callback.set(_onloadCallback);
_notify(callback);
}
if (_onloadendCallback)
{
callback.set(_onloadendCallback);
_notify(callback);
}
}
/**
* @brief Send out request and fire callback when done.
@ -259,13 +281,19 @@ void MinXmlHttpRequest::_sendRequest(JSContext *cx)
_httpRequest->release();
}
MinXmlHttpRequest::MinXmlHttpRequest()
: _url()
{
MinXmlHttpRequest(ScriptingCore::getInstance()->getGlobalContext());
}
/**
* @brief Constructor initializes cchttprequest and stuff
*
*/
MinXmlHttpRequest::MinXmlHttpRequest()
MinXmlHttpRequest::MinXmlHttpRequest(JSContext *cx)
: _url()
, _cx(ScriptingCore::getInstance()->getGlobalContext())
, _cx(cx)
, _meth()
, _type()
, _data(nullptr)
@ -284,18 +312,16 @@ MinXmlHttpRequest::MinXmlHttpRequest()
, _httpHeader()
, _requestHeader()
, _isAborted(false)
, _onreadystateCallback(nullptr)
, _onloadstartCallback(nullptr)
, _onabortCallback(nullptr)
, _onerrorCallback(nullptr)
, _onloadCallback(nullptr)
, _onloadendCallback(nullptr)
, _ontimeoutCallback(nullptr)
{
_scheduler = cocos2d::Director::getInstance()->getScheduler();
_scheduler->retain();
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
_onreadystateCallback.construct(cx);
_onloadstartCallback.construct(cx);
_onabortCallback.construct(cx);
_onerrorCallback.construct(cx);
_onloadCallback.construct(cx);
_onloadendCallback.construct(cx);
_ontimeoutCallback.construct(cx);
}
/**
@ -304,13 +330,42 @@ MinXmlHttpRequest::MinXmlHttpRequest()
*/
MinXmlHttpRequest::~MinXmlHttpRequest()
{
_onreadystateCallback.destroyIfConstructed();
_onloadstartCallback.destroyIfConstructed();
_onloadendCallback.destroyIfConstructed();
_onloadCallback.destroyIfConstructed();
_onerrorCallback.destroyIfConstructed();
_onabortCallback.destroyIfConstructed();
_ontimeoutCallback.destroyIfConstructed();
JS::RootedValue callback(_cx);
if (_onreadystateCallback)
{
callback.set(OBJECT_TO_JSVAL(_onreadystateCallback));
js_remove_object_root(callback);
}
if (_onloadstartCallback)
{
callback.set(OBJECT_TO_JSVAL(_onloadstartCallback));
js_remove_object_root(callback);
}
if (_onabortCallback)
{
callback.set(OBJECT_TO_JSVAL(_onabortCallback));
js_remove_object_root(callback);
}
if (_onerrorCallback)
{
callback.set(OBJECT_TO_JSVAL(_onerrorCallback));
js_remove_object_root(callback);
}
if (_onloadCallback)
{
callback.set(OBJECT_TO_JSVAL(_onloadCallback));
js_remove_object_root(callback);
}
if (_onloadendCallback)
{
callback.set(OBJECT_TO_JSVAL(_onloadendCallback));
js_remove_object_root(callback);
}
if (_ontimeoutCallback)
{
callback.set(OBJECT_TO_JSVAL(_ontimeoutCallback));
js_remove_object_root(callback);
}
if (_httpRequest)
{
@ -335,7 +390,7 @@ JS_BINDED_CLASS_GLUE_IMPL(MinXmlHttpRequest);
JS_BINDED_CONSTRUCTOR_IMPL(MinXmlHttpRequest)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
MinXmlHttpRequest* req = new (std::nothrow) MinXmlHttpRequest();
MinXmlHttpRequest* req = new (std::nothrow) MinXmlHttpRequest(cx);
JS::RootedObject proto(cx, MinXmlHttpRequest::js_proto);
JS::RootedObject parentProto(cx, MinXmlHttpRequest::js_parent);
@ -378,9 +433,9 @@ JS_BINDED_CONSTRUCTOR_IMPL(MinXmlHttpRequest)
*/
#define GETTER_SETTER_FOR_CALLBACK_PROP(x,y) JS_BINDED_PROP_GET_IMPL(MinXmlHttpRequest, x)\
{\
if (y.ref())\
if (y)\
{\
JS::RootedValue out(cx, OBJECT_TO_JSVAL(y.ref()));\
JS::RootedValue out(cx, OBJECT_TO_JSVAL(y));\
args.rval().set(out);\
}\
else\
@ -394,12 +449,13 @@ JS_BINDED_PROP_SET_IMPL(MinXmlHttpRequest, x)\
JS::RootedValue callback(cx, args.get(0));\
if (!callback.isNullOrUndefined())\
{\
js_proxy_t *p = jsb_get_native_proxy(this);\
if (p) {\
JS::RootedObject thisObj(cx, p->obj);\
JS_SetProperty(cx, thisObj, "y", callback);\
if (y)\
{\
JS::RootedValue oldCallback(cx, OBJECT_TO_JSVAL(y));\
js_remove_object_root(oldCallback);\
}\
y.ref() = callback.toObjectOrNull();\
js_add_object_root(callback);\
y = callback.toObjectOrNull();\
}\
return true;\
}
@ -775,7 +831,11 @@ JS_BINDED_FUNC_IMPL(MinXmlHttpRequest, send)
_setHttpRequestHeader();
_sendRequest(cx);
_notify(_onloadstartCallback.ref());
if (_onloadstartCallback)
{
JS::RootedObject callback(cx, _onloadstartCallback);
_notify(callback);
}
//begin schedule for timeout
if(_timeout > 0)
@ -791,7 +851,11 @@ void MinXmlHttpRequest::update(float dt)
_elapsedTime += dt;
if(_elapsedTime * 1000 >= _timeout)
{
_notify(_ontimeoutCallback.ref());
if (_ontimeoutCallback)
{
JS::RootedObject callback(_cx, _ontimeoutCallback);
_notify(callback);
}
_elapsedTime = 0;
_readyState = UNSENT;
_scheduler->unscheduleAllForTarget(this);
@ -813,7 +877,11 @@ JS_BINDED_FUNC_IMPL(MinXmlHttpRequest, abort)
//3.Change the state to UNSENT.
_readyState = UNSENT;
_notify(_onabortCallback.ref());
if (_onabortCallback)
{
JS::RootedObject callback(cx, _onabortCallback);
_notify(callback);
}
return true;
}
@ -946,15 +1014,14 @@ void MinXmlHttpRequest::_notify(JS::HandleObject callback)
if(p)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
if (callback)
{
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedObject obj(_cx, p->obj);
JSAutoCompartment ac(_cx, obj);
//JS_IsExceptionPending(cx) && JS_ReportPendingException(cx);
JS::RootedValue fval(cx, OBJECT_TO_JSVAL(callback));
JS::RootedValue out(cx);
JS_CallFunctionValue(cx, JS::NullPtr(), fval, JS::HandleValueArray::empty(), &out);
JS::RootedValue callbackVal(_cx, OBJECT_TO_JSVAL(callback));
JS::RootedValue out(_cx);
JS_CallFunctionValue(_cx, JS::NullPtr(), callbackVal, JS::HandleValueArray::empty(), &out);
}
}

View File

@ -56,6 +56,7 @@ public:
static const unsigned short DONE = 4;
MinXmlHttpRequest();
MinXmlHttpRequest(JSContext *cx);
~MinXmlHttpRequest();
JS_BINDED_CLASS_GLUE(MinXmlHttpRequest);
@ -102,13 +103,13 @@ private:
std::string _type;
char* _data;
uint32_t _dataSize;
mozilla::Maybe<JS::RootedObject> _onloadstartCallback;
mozilla::Maybe<JS::RootedObject> _onabortCallback;
mozilla::Maybe<JS::RootedObject> _onerrorCallback;
mozilla::Maybe<JS::RootedObject> _onloadCallback;
mozilla::Maybe<JS::RootedObject> _onloadendCallback;
mozilla::Maybe<JS::RootedObject> _ontimeoutCallback;
mozilla::Maybe<JS::RootedObject> _onreadystateCallback;
JS::Heap<JSObject*> _onloadstartCallback;
JS::Heap<JSObject*> _onabortCallback;
JS::Heap<JSObject*> _onerrorCallback;
JS::Heap<JSObject*> _onloadCallback;
JS::Heap<JSObject*> _onloadendCallback;
JS::Heap<JSObject*> _ontimeoutCallback;
JS::Heap<JSObject*> _onreadystateCallback;
int _readyState;
long _status;
std::string _statusText;

View File

@ -116,13 +116,7 @@ class JSB_EditBoxDelegate
public:
JSB_EditBoxDelegate()
{
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
_JSDelegate.construct(cx, JS::NullHandleValue);
}
virtual ~JSB_EditBoxDelegate()
{
_JSDelegate.destroyIfConstructed();
_JSDelegate = JS::NullValue();
}
virtual void editBoxEditingDidBegin(EditBox* editBox) override
@ -131,7 +125,8 @@ public:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(_JSDelegate.ref().get(), "editBoxEditingDidBegin", 1, &arg);
JS::RootedValue delegateVal(ScriptingCore::getInstance()->getGlobalContext(), _JSDelegate);
ScriptingCore::getInstance()->executeFunctionWithOwner(delegateVal, "editBoxEditingDidBegin", 1, &arg);
}
virtual void editBoxEditingDidEnd(EditBox* editBox) override
@ -140,7 +135,8 @@ public:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(_JSDelegate.ref().get(), "editBoxEditingDidEnd", 1, &arg);
JS::RootedValue delegateVal(ScriptingCore::getInstance()->getGlobalContext(), _JSDelegate);
ScriptingCore::getInstance()->executeFunctionWithOwner(delegateVal, "editBoxEditingDidEnd", 1, &arg);
}
virtual void editBoxTextChanged(EditBox* editBox, const std::string& text) override
@ -148,12 +144,15 @@ public:
js_proxy_t * p = jsb_get_native_proxy(editBox);
if (!p) return;
JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
jsval dataVal[2];
dataVal[0] = OBJECT_TO_JSVAL(p->obj);
std::string arg1 = text;
dataVal[1] = std_string_to_jsval(ScriptingCore::getInstance()->getGlobalContext(), arg1);
dataVal[1] = std_string_to_jsval(cx, arg1);
ScriptingCore::getInstance()->executeFunctionWithOwner(_JSDelegate.ref().get(), "editBoxTextChanged", 2, dataVal);
JS::RootedValue delegateVal(cx, _JSDelegate);
ScriptingCore::getInstance()->executeFunctionWithOwner(delegateVal, "editBoxTextChanged", 2, dataVal);
}
virtual void editBoxReturn(EditBox* editBox) override
@ -162,15 +161,16 @@ public:
if (!p) return;
jsval arg = OBJECT_TO_JSVAL(p->obj);
ScriptingCore::getInstance()->executeFunctionWithOwner(_JSDelegate.ref().get(), "editBoxReturn", 1, &arg);
JS::RootedValue delegateVal(ScriptingCore::getInstance()->getGlobalContext(), _JSDelegate);
ScriptingCore::getInstance()->executeFunctionWithOwner(delegateVal, "editBoxReturn", 1, &arg);
}
void setJSDelegate(JS::HandleValue pJSDelegate)
{
_JSDelegate.ref() = pJSDelegate;
_JSDelegate = pJSDelegate;
}
private:
mozilla::Maybe<JS::RootedValue> _JSDelegate;
JS::Heap<JS::Value> _JSDelegate;
};
static bool js_cocos2dx_CCEditBox_setDelegate(JSContext *cx, uint32_t argc, jsval *vp)