fix JSB Memory leaks and crashes (#18577)

* [game] Uses global compartment.

* fixed cocostudio bug.

* Fixes Memory leak for JSB.

* Memory leak in ActionsTest.js

* js_callfunc binding check whether jsThis is valid.

* Fixes potential crash in DownloadDelegator .

* CCLOG -> CCLOGINFO for garbage collect callback.

* jsb_c_proxy_s is a struct which contains a JS::Heap<> cpp object. Need to use `new`/`delete` to manage its memory.

* The functionality of JS controls C++ object's lifecycle isn't stable enough, please don't enable it now. Make an error if user enables it.

* Compilation error fixes.

* Removes unused JSAutoCompartment since we use JS_EnterCompartment/JS_LeaveCompartment now.
This commit is contained in:
James Chen 2018-01-10 14:39:45 +08:00 committed by minggo
parent 8f1459b8ef
commit b2ecbca549
17 changed files with 325 additions and 449 deletions

View File

@ -76,7 +76,8 @@ bool JSB_cpConstraint_getBodyA(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpConstraintGetBodyA((cpConstraint*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpBody_object), JSB_cpBody_class, "cpBody" ));
JS::RootedObject rootedObj(cx, JSB_cpBody_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpBody_class, "cpBody" ));
return true;
}
@ -94,7 +95,8 @@ bool JSB_cpConstraint_getBodyB(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpConstraintGetBodyB((cpConstraint*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpBody_object), JSB_cpBody_class, "cpBody" ));
JS::RootedObject rootedObj(cx, JSB_cpBody_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpBody_class, "cpBody" ));
return true;
}
@ -202,7 +204,8 @@ bool JSB_cpConstraint_getSpace(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpConstraintGetSpace((cpConstraint*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpSpace_object), JSB_cpSpace_class, "cpSpace" ));
JS::RootedObject rootedObj(cx, JSB_cpSpace_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpSpace_class, "cpSpace" ));
return true;
}
@ -526,7 +529,8 @@ void JSB_cpConstraint_createClass(JSContext *cx, JS::HandleObject globalObj, con
JS_FS_END
};
JSB_cpConstraint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpBase_object), JSB_cpConstraint_class, JSB_cpConstraint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpBase_object);
JSB_cpConstraint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpConstraint_class, JSB_cpConstraint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -732,7 +736,8 @@ void JSB_cpGrooveJoint_createClass(JSContext *cx, JS::HandleObject globalObj, co
JS_FS_END
};
JSB_cpGrooveJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpGrooveJoint_class, JSB_cpGrooveJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpGrooveJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpGrooveJoint_class, JSB_cpGrooveJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -850,7 +855,8 @@ void JSB_cpSimpleMotor_createClass(JSContext *cx, JS::HandleObject globalObj, co
JS_FS_END
};
JSB_cpSimpleMotor_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpSimpleMotor_class, JSB_cpSimpleMotor_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpSimpleMotor_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpSimpleMotor_class, JSB_cpSimpleMotor_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -1011,7 +1017,8 @@ void JSB_cpPivotJoint_createClass(JSContext *cx, JS::HandleObject globalObj, con
JS_FS_END
};
JSB_cpPivotJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpPivotJoint_class, JSB_cpPivotJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpPivotJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpPivotJoint_class, JSB_cpPivotJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -1216,7 +1223,8 @@ void JSB_cpPinJoint_createClass(JSContext *cx, JS::HandleObject globalObj, const
JS_FS_END
};
JSB_cpPinJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpPinJoint_class, JSB_cpPinJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpPinJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpPinJoint_class, JSB_cpPinJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -1466,7 +1474,8 @@ void JSB_cpSlideJoint_createClass(JSContext *cx, JS::HandleObject globalObj, con
JS_FS_END
};
JSB_cpSlideJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpSlideJoint_class, JSB_cpSlideJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpSlideJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpSlideJoint_class, JSB_cpSlideJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -1628,7 +1637,8 @@ void JSB_cpGearJoint_createClass(JSContext *cx, JS::HandleObject globalObj, cons
JS_FS_END
};
JSB_cpGearJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpGearJoint_class, JSB_cpGearJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpGearJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpGearJoint_class, JSB_cpGearJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -1834,7 +1844,8 @@ void JSB_cpDampedRotarySpring_createClass(JSContext *cx, JS::HandleObject global
JS_FS_END
};
JSB_cpDampedRotarySpring_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpDampedRotarySpring_class, JSB_cpDampedRotarySpring_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpDampedRotarySpring_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpDampedRotarySpring_class, JSB_cpDampedRotarySpring_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -2128,7 +2139,8 @@ void JSB_cpDampedSpring_createClass(JSContext *cx, JS::HandleObject globalObj, c
JS_FS_END
};
JSB_cpDampedSpring_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpDampedSpring_class, JSB_cpDampedSpring_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpDampedSpring_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpDampedSpring_class, JSB_cpDampedSpring_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -2333,7 +2345,8 @@ void JSB_cpRatchetJoint_createClass(JSContext *cx, JS::HandleObject globalObj, c
JS_FS_END
};
JSB_cpRatchetJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpRatchetJoint_class, JSB_cpRatchetJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpRatchetJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpRatchetJoint_class, JSB_cpRatchetJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -2495,7 +2508,8 @@ void JSB_cpRotaryLimitJoint_createClass(JSContext *cx, JS::HandleObject globalOb
JS_FS_END
};
JSB_cpRotaryLimitJoint_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpConstraint_object), JSB_cpRotaryLimitJoint_class, JSB_cpRotaryLimitJoint_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpConstraint_object);
JSB_cpRotaryLimitJoint_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpRotaryLimitJoint_class, JSB_cpRotaryLimitJoint_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -3090,7 +3104,8 @@ void JSB_cpArbiter_createClass(JSContext *cx, JS::HandleObject globalObj, const
JS_FS_END
};
JSB_cpArbiter_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpBase_object), JSB_cpArbiter_class, JSB_cpArbiter_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpBase_object);
JSB_cpArbiter_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpArbiter_class, JSB_cpArbiter_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -3380,7 +3395,8 @@ bool JSB_cpSpace_getStaticBody(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpSpaceGetStaticBody((cpSpace*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpBody_object), JSB_cpBody_class, "cpBody" ));
JS::RootedObject rootedObj(cx, JSB_cpBody_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpBody_class, "cpBody" ));
return true;
}
@ -3398,7 +3414,8 @@ bool JSB_cpSpace_init(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpSpaceInit((cpSpace*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpSpace_object), JSB_cpSpace_class, "cpSpace" ));
JS::RootedObject rootedObj(cx, JSB_cpSpace_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpSpace_class, "cpSpace" ));
return true;
}
@ -3779,7 +3796,8 @@ void JSB_cpSpace_createClass(JSContext *cx, JS::HandleObject globalObj, const ch
JS_FS_END
};
JSB_cpSpace_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpBase_object), JSB_cpSpace_class, JSB_cpSpace_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpBase_object);
JSB_cpSpace_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpSpace_class, JSB_cpSpace_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -4116,7 +4134,8 @@ bool JSB_cpBody_getSpace(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpBodyGetSpace((cpBody*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpSpace_object), JSB_cpSpace_class, "cpSpace" ));
JS::RootedObject rootedObj(cx, JSB_cpSpace_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpSpace_class, "cpSpace" ));
return true;
}
@ -4243,7 +4262,8 @@ bool JSB_cpBody_init(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpBodyInit((cpBody*)arg0 , (cpFloat)arg1 , (cpFloat)arg2 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpBody_object), JSB_cpBody_class, "cpBody" ));
JS::RootedObject rootedObj(cx, JSB_cpBody_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpBody_class, "cpBody" ));
return true;
}
@ -4717,7 +4737,8 @@ void JSB_cpBody_createClass(JSContext *cx, JS::HandleObject globalObj, const cha
JS_FS_END
};
JSB_cpBody_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpBase_object), JSB_cpBody_class, JSB_cpBody_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpBase_object);
JSB_cpBody_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpBody_class, JSB_cpBody_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -4862,7 +4883,8 @@ bool JSB_cpShape_getBody(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpShapeGetBody((cpShape*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpBody_object), JSB_cpBody_class, "cpBody" ));
JS::RootedObject rootedObj(cx, JSB_cpBody_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpBody_class, "cpBody" ));
return true;
}
@ -5042,7 +5064,8 @@ bool JSB_cpShape_getSpace(JSContext *cx, uint32_t argc, jsval *vp) {
ret_val = cpShapeGetSpace((cpShape*)arg0 );
args.rval().set(c_class_to_jsval( cx, ret_val, JS::RootedObject(cx,JSB_cpSpace_object), JSB_cpSpace_class, "cpSpace" ));
JS::RootedObject rootedObj(cx, JSB_cpSpace_object);
args.rval().set(c_class_to_jsval( cx, ret_val, rootedObj, JSB_cpSpace_class, "cpSpace" ));
return true;
}
@ -5349,7 +5372,8 @@ void JSB_cpShape_createClass(JSContext *cx, JS::HandleObject globalObj, const ch
JS_FS_END
};
JSB_cpShape_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpBase_object), JSB_cpShape_class, JSB_cpShape_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpBase_object);
JSB_cpShape_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpShape_class, JSB_cpShape_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -5462,7 +5486,8 @@ void JSB_cpCircleShape_createClass(JSContext *cx, JS::HandleObject globalObj, co
JS_FS_END
};
JSB_cpCircleShape_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpShape_object), JSB_cpCircleShape_class, JSB_cpCircleShape_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpShape_object);
JSB_cpCircleShape_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpCircleShape_class, JSB_cpCircleShape_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -5639,7 +5664,8 @@ void JSB_cpSegmentShape_createClass(JSContext *cx, JS::HandleObject globalObj, c
JS_FS_END
};
JSB_cpSegmentShape_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpShape_object), JSB_cpSegmentShape_class, JSB_cpSegmentShape_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpShape_object);
JSB_cpSegmentShape_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpSegmentShape_class, JSB_cpSegmentShape_constructor,0,properties,funcs,NULL,st_funcs);
}
/*
@ -5753,7 +5779,8 @@ void JSB_cpPolyShape_createClass(JSContext *cx, JS::HandleObject globalObj, cons
JS_FS_END
};
JSB_cpPolyShape_object = JS_InitClass(cx, globalObj, JS::RootedObject(cx,JSB_cpShape_object), JSB_cpPolyShape_class, JSB_cpPolyShape_constructor,0,properties,funcs,NULL,st_funcs);
JS::RootedObject rootedObj(cx, JSB_cpShape_object);
JSB_cpPolyShape_object = JS_InitClass(cx, globalObj, rootedObj, JSB_cpPolyShape_class, JSB_cpPolyShape_constructor,0,properties,funcs,NULL,st_funcs);
}

View File

@ -74,6 +74,10 @@
#define TRACE_DEBUGGER_SERVER(...)
#endif // #if COCOS2D_DEBUG
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
#error "The functionality of JS controls C++ object's lifecycle isn't stable enough, please don't enable it now."
#endif
#define BYTE_CODE_FILE_EXT ".jsc"
using namespace cocos2d;
@ -121,6 +125,22 @@ static void ReportException(JSContext *cx)
}
}
static void onGarbageCollect(JSRuntime* rt, JSGCStatus status, void* data)
{
/* We finalize any pending toggle refs before doing any garbage collection,
* so that we can collect the JS wrapper objects, and in order to minimize
* the chances of objects having a pending toggle up queued when they are
* garbage collected. */
if (status == JSGC_BEGIN)
{
CCLOGINFO("onGarbageCollect begin, native->js map: %d, js->native map: %d", (int)_native_js_global_map.size(), (int)_js_native_global_map.size());
}
else if (status == JSGC_END)
{
CCLOGINFO("onGarbageCollect end, native->js map: %d, js->native map: %d", (int)_native_js_global_map.size(), (int)_js_native_global_map.size());
}
}
static void executeJSFunctionFromReservedSpot(JSContext *cx, JS::HandleObject obj,
const JS::HandleValueArray& dataVal, JS::MutableHandleValue retval) {
@ -128,7 +148,6 @@ static void executeJSFunctionFromReservedSpot(JSContext *cx, JS::HandleObject ob
if (func.isNullOrUndefined()) { return; }
JS::RootedValue thisObj(cx, JS_GetReservedSlot(obj, 1));
JSAutoCompartment ac(cx, obj);
if (thisObj.isNullOrUndefined()) {
JS_CallFunctionValue(cx, obj, func, dataVal, retval);
@ -471,6 +490,7 @@ ScriptingCore::ScriptingCore()
, _needCleanup(false)
, _global(nullptr)
, _debugGlobal(nullptr)
, _oldCompartment(nullptr)
, _callFromScript(false)
, _finalizing(nullptr)
{
@ -510,7 +530,6 @@ void ScriptingCore::string_report(JS::HandleValue val) {
bool ScriptingCore::evalString(const char *string, JS::MutableHandleValue outVal, const char *filename, JSContext* cx, JS::HandleObject global)
{
JSAutoCompartment ac(cx, global);
JS::PersistentRootedScript script(cx);
JS::CompileOptions op(cx);
@ -637,14 +656,14 @@ void ScriptingCore::createGlobalContext() {
JS_SetGCZeal(this->_cx, 2, JS_DEFAULT_ZEAL_FREQ);
#endif
_global = new (std::nothrow) JS::PersistentRootedObject(_rt, NewGlobalObject(_cx));
JS_SetGCCallback(_rt, onGarbageCollect, nullptr);
_global = new (std::nothrow) JS::PersistentRootedObject(_rt, newGlobalObject(_cx, false));
JS::RootedObject global(_cx, _global->get());
// Removed in Firefox v34
js::SetDefaultObjectForContext(_cx, global);
JSAutoCompartment ac(_cx, _global->get());
runScript("script/jsb_prepare.js");
for (auto& callback : registrationList) {
@ -696,7 +715,6 @@ JS::PersistentRootedScript* ScriptingCore::compileScript(const std::string& path
cocos2d::FileUtils *futil = cocos2d::FileUtils::getInstance();
JSAutoCompartment ac(cx, global);
script = new (std::nothrow) JS::PersistentRootedScript(cx);
if (script == nullptr) {
return nullptr;
@ -811,7 +829,6 @@ bool ScriptingCore::runScript(const std::string& path, JS::HandleObject global,
bool evaluatedOK = false;
if (script) {
JS::RootedValue rval(cx);
JSAutoCompartment ac(cx, global);
evaluatedOK = JS_ExecuteScript(cx, global, *script, &rval);
if (false == evaluatedOK) {
cocos2d::log("Evaluating %s failed (evaluatedOK == JS_FALSE)", path.c_str());
@ -840,7 +857,6 @@ bool ScriptingCore::requireScript(const char *path, JS::HandleObject global, JSC
bool evaluatedOK = false;
if (script)
{
JSAutoCompartment ac(cx, global);
evaluatedOK = JS_ExecuteScript(cx, global, (*script), jsvalRet);
if (false == evaluatedOK)
{
@ -902,11 +918,15 @@ void ScriptingCore::cleanup()
CC_SAFE_DELETE(_global);
CC_SAFE_DELETE(_debugGlobal);
JS_LeaveCompartment(_cx, _oldCompartment);
_oldCompartment = nullptr;
if (_cx)
{
JS_DestroyContext(_cx);
_cx = NULL;
}
if (_rt)
{
JS_DestroyRuntime(_rt);
@ -950,7 +970,6 @@ bool ScriptingCore::log(JSContext* cx, uint32_t argc, jsval *vp)
void ScriptingCore::retainScriptObject(cocos2d::Ref* owner, cocos2d::Ref* target)
{
JS::RootedObject global(_cx, _global->get());
JSAutoCompartment ac(_cx, global);
JS::RootedObject jsbObj(_cx);
get_or_create_js_obj(_cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(_cx, OBJECT_TO_JSVAL(jsbObj));
@ -984,7 +1003,6 @@ void ScriptingCore::retainScriptObject(cocos2d::Ref* owner, cocos2d::Ref* target
void ScriptingCore::rootScriptObject(cocos2d::Ref* target)
{
JS::RootedObject global(_cx, _global->get());
JSAutoCompartment ac(_cx, global);
JS::RootedObject jsbObj(_cx);
get_or_create_js_obj(_cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(_cx, OBJECT_TO_JSVAL(jsbObj));
@ -1019,7 +1037,6 @@ void ScriptingCore::rootScriptObject(cocos2d::Ref* target)
void ScriptingCore::releaseScriptObject(cocos2d::Ref* owner, cocos2d::Ref* target)
{
JS::RootedObject global(_cx, _global->get());
JSAutoCompartment ac(_cx, global);
JS::RootedObject jsbObj(_cx);
get_or_create_js_obj(_cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(_cx, OBJECT_TO_JSVAL(jsbObj));
@ -1053,7 +1070,6 @@ void ScriptingCore::releaseScriptObject(cocos2d::Ref* owner, cocos2d::Ref* targe
void ScriptingCore::unrootScriptObject(cocos2d::Ref* target)
{
JS::RootedObject global(_cx, _global->get());
JSAutoCompartment ac(_cx, global);
JS::RootedObject jsbObj(_cx);
get_or_create_js_obj(_cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(_cx, OBJECT_TO_JSVAL(jsbObj));
@ -1098,7 +1114,6 @@ void ScriptingCore::releaseAllChildrenRecursive(cocos2d::Node *node)
void ScriptingCore::releaseAllNativeRefs(cocos2d::Ref* owner)
{
JS::RootedObject global(_cx, _global->get());
JSAutoCompartment ac(_cx, global);
JS::RootedObject jsbObj(_cx);
get_or_create_js_obj(_cx, global, "jsb", &jsbObj);
JS::RootedValue jsbVal(_cx, OBJECT_TO_JSVAL(jsbObj));
@ -1239,7 +1254,6 @@ void ScriptingCore::cleanupSchedulesAndActions(js_proxy_t* p)
bool ScriptingCore::isFunctionOverridedInJS(JS::HandleObject obj, const std::string& name, JSNative native)
{
JS::RootedObject jsobj(_cx, obj);
JSAutoCompartment ac(_cx, jsobj);
JS::RootedValue value(_cx);
bool ok = JS_GetProperty(_cx, jsobj, name.c_str(), &value);
if (ok && !value.isNullOrUndefined() && !JS_IsNativeFunction(value.toObjectOrNull(), native))
@ -1265,8 +1279,6 @@ int ScriptingCore::handleActionEvent(void* data)
js_proxy_t * p = jsb_get_native_proxy(actionObject);
if (!p) return 0;
JSAutoCompartment ac(_cx, _global->get());
int ret = 0;
JS::RootedValue retval(_cx);
@ -1297,8 +1309,6 @@ int ScriptingCore::handleNodeEvent(void* data)
js_proxy_t * p = jsb_get_native_proxy(node);
if (!p) return 0;
JSAutoCompartment ac(_cx, _global->get());
int ret = 0;
JS::RootedValue retval(_cx);
jsval dataVal = INT_TO_JSVAL(1);
@ -1362,8 +1372,6 @@ int ScriptingCore::handleComponentEvent(void* data)
js_proxy_t * p = jsb_get_native_proxy(node);
if (!p) return 0;
JSAutoCompartment ac(_cx, _global->get());
int ret = 0;
JS::RootedValue retval(_cx);
jsval dataVal = INT_TO_JSVAL(1);
@ -1404,8 +1412,6 @@ bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::Eve
bool ScriptingCore::handleTouchesEvent(void* nativeObj, cocos2d::EventTouch::EventCode eventCode, const std::vector<cocos2d::Touch*>& touches, cocos2d::Event* event, JS::MutableHandleValue jsvalRet)
{
JSAutoCompartment ac(_cx, _global->get());
bool ret = false;
std::string funcName = getTouchesFuncName(eventCode);
JS::RootedObject jsretArr(_cx, JS_NewArrayObject(_cx, 0));
@ -1450,8 +1456,6 @@ bool ScriptingCore::handleTouchEvent(void* nativeObj, cocos2d::EventTouch::Event
bool ScriptingCore::handleTouchEvent(void* nativeObj, cocos2d::EventTouch::EventCode eventCode, cocos2d::Touch* touch, cocos2d::Event* event, JS::MutableHandleValue jsvalRet)
{
JSAutoCompartment ac(_cx, _global->get());
std::string funcName = getTouchFuncName(eventCode);
bool ret = false;
@ -1481,8 +1485,6 @@ bool ScriptingCore::handleMouseEvent(void* nativeObj, cocos2d::EventMouse::Mouse
bool ScriptingCore::handleMouseEvent(void* nativeObj, cocos2d::EventMouse::MouseEventType eventType, cocos2d::Event* event, JS::MutableHandleValue jsvalRet)
{
JSAutoCompartment ac(_cx, _global->get());
std::string funcName = getMouseFuncName(eventType);
bool ret = false;
@ -1551,8 +1553,6 @@ bool ScriptingCore::executeFunctionWithOwner(jsval owner, const char *name, cons
do
{
JSAutoCompartment ac(cx, obj);
if (JS_HasProperty(cx, obj, name, &hasFunc) && hasFunc) {
if (!JS_GetProperty(cx, obj, name, &funcVal)) {
break;
@ -1575,8 +1575,6 @@ std::chrono::steady_clock::time_point ScriptingCore::getEngineStartTime() const
bool ScriptingCore::handleKeyboardEvent(void* nativeObj, cocos2d::EventKeyboard::KeyCode keyCode, bool isPressed, cocos2d::Event* event)
{
JSAutoCompartment ac(_cx, _global->get());
js_proxy_t * p = jsb_get_native_proxy(nativeObj);
if (nullptr == p)
return false;
@ -1605,8 +1603,6 @@ bool ScriptingCore::handleKeyboardEvent(void* nativeObj, cocos2d::EventKeyboard:
bool ScriptingCore::handleFocusEvent(void* nativeObj, cocos2d::ui::Widget* widgetLoseFocus, cocos2d::ui::Widget* widgetGetFocus)
{
JSAutoCompartment ac(_cx, _global->get());
js_proxy_t * p = jsb_get_native_proxy(nativeObj);
if (nullptr == p)
return false;
@ -1627,8 +1623,6 @@ bool ScriptingCore::handleFocusEvent(void* nativeObj, cocos2d::ui::Widget* widge
int ScriptingCore::executeCustomTouchesEvent(EventTouch::EventCode eventType,
const std::vector<Touch*>& touches, JSObject *obj)
{
JSAutoCompartment ac(_cx, _global->get());
std::string funcName = getTouchesFuncName(eventType);
JS::RootedObject jsretArr(_cx, JS_NewArrayObject(this->_cx, 0));
@ -1654,8 +1648,6 @@ int ScriptingCore::executeCustomTouchesEvent(EventTouch::EventCode eventType,
int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType, Touch *touch, JSObject *obj)
{
JSAutoCompartment ac(_cx, _global->get());
JS::RootedValue retval(_cx);
std::string funcName = getTouchFuncName(eventType);
@ -1686,8 +1678,6 @@ int ScriptingCore::executeCustomTouchEvent(EventTouch::EventCode eventType,
int ScriptingCore::executeGlobalFunction(const char* functionName)
{
JSAutoCompartment ac(_cx, _global->get());
std::string evalStr = functionName;
JS::RootedValue globalVal(_cx, OBJECT_TO_JSVAL(_global->get()));
return executeFunctionWithOwner(globalVal, functionName, 0, NULL);
@ -1757,6 +1747,11 @@ bool ScriptingCore::isObjectValid(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (argc == 1) {
if (!args[0].isObject())
{
args.rval().setBoolean(false);
return true;
}
JS::RootedObject tmpObj(cx, args.get(0).toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(tmpObj);
if (proxy && proxy->ptr) {
@ -1851,8 +1846,6 @@ void SimpleRunLoop::update(float dt)
void ScriptingCore::debugProcessInput(const std::string& str)
{
JSAutoCompartment ac(_cx, _debugGlobal->get());
JSString* jsstr = JS_NewStringCopyZ(_cx, str.c_str());
jsval argv = STRING_TO_JSVAL(jsstr);
JS::RootedValue outval(_cx);
@ -2076,11 +2069,9 @@ void ScriptingCore::enableDebugger(unsigned int port)
{
if (!_debugGlobal)
{
JSAutoCompartment ac0(_cx, _global->get());
JS_SetDebugMode(_cx, true);
_debugGlobal = new (std::nothrow) JS::PersistentRootedObject(_cx, NewGlobalObject(_cx, true));
_debugGlobal = new (std::nothrow) JS::PersistentRootedObject(_cx, newGlobalObject(_cx, true));
// Adds the debugger object to root, otherwise it may be collected by GC.
//AddObjectRoot(_cx, &_debugGlobal.ref()); no need, it's persistent rooted now
//JS_WrapObject(_cx, &_debugGlobal.ref()); Not really needed, JS_WrapObject makes a cross-compartment wrapper for the given JS object
@ -2117,7 +2108,7 @@ void ScriptingCore::enableDebugger(unsigned int port)
}
}
JSObject* NewGlobalObject(JSContext* cx, bool debug)
JSObject* ScriptingCore::newGlobalObject(JSContext* cx, bool debug)
{
JS::CompartmentOptions options;
options.setVersion(JSVERSION_LATEST);
@ -2126,7 +2117,19 @@ JSObject* NewGlobalObject(JSContext* cx, bool debug)
if (!glob) {
return nullptr;
}
JSAutoCompartment ac(cx, glob);
JSCompartment* oldDebugCompartment = nullptr;
if (!debug)
{
_oldCompartment = JS_EnterCompartment(cx, glob);
}
else
{
oldDebugCompartment = JS_EnterCompartment(cx, glob);
}
bool ok = true;
ok = JS_InitStandardClasses(cx, glob);
if (ok)
@ -2138,6 +2141,11 @@ JSObject* NewGlobalObject(JSContext* cx, bool debug)
JS_FireOnNewGlobalObject(cx, glob);
if (debug)
{
JS_LeaveCompartment(cx, oldDebugCompartment);
}
return glob;
}
@ -2173,7 +2181,7 @@ js_proxy_t* jsb_new_proxy(void* nativeObj, JS::HandleObject jsHandle)
if (nativeObj && jsObj)
{
// native to JS index
proxy = (js_proxy_t *)malloc(sizeof(js_proxy_t));
proxy = new (std::nothrow) js_proxy_t();
CC_ASSERT(proxy && "not enough memory");
#if 0
@ -2252,7 +2260,7 @@ void jsb_remove_proxy(js_proxy_t* proxy)
if (it_js != _js_native_global_map.end())
{
// Free it once, since we only have one proxy alloced entry
free(it_js->second);
delete it_js->second;
_js_native_global_map.erase(it_js);
}
else CCLOG("jsb_remove_proxy: failed. JS key not found");
@ -2367,9 +2375,7 @@ JSObject* jsb_get_or_create_weak_jsobject(JSContext *cx, void *native, js_type_c
JS::RootedValue flagVal(cx, OBJECT_TO_JSVAL(flag));
JS_SetProperty(cx, jsObj, "__cppCreated", flagVal);
#if ! CC_ENABLE_GC_FOR_NATIVE_OBJECTS
JS::AddNamedObjectRoot(cx, &proxy->obj, debug);
#else
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
js_add_FinalizeHook(cx, jsObj, false);
#if COCOS2D_DEBUG > 1
if (debug != nullptr)

View File

@ -84,6 +84,7 @@ private:
JSContext *_cx;
JS::PersistentRootedObject *_global;
JS::PersistentRootedObject *_debugGlobal;
JSCompartment *_oldCompartment;
SimpleRunLoop* _runLoop;
bool _jsInited;
bool _needCleanup;
@ -556,6 +557,8 @@ private:
void string_report(JS::HandleValue val);
void initRegister();
JSObject* newGlobalObject(JSContext* cx, bool debug);
public:
int handleNodeEvent(void* data);
int handleActionEvent(void* data);
@ -576,7 +579,6 @@ public:
void restartVM();
};
JSObject* NewGlobalObject(JSContext* cx, bool debug = false);
bool jsb_set_reserved_slot(JSObject *obj, uint32_t idx, jsval value);
bool jsb_get_reserved_slot(JSObject *obj, uint32_t idx, jsval& ret);

View File

@ -601,7 +601,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));
@ -627,7 +627,7 @@ 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());
@ -657,7 +657,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));
@ -687,7 +687,6 @@ 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 jsbObj(cx);
get_or_create_js_obj(cx, global, "jsb", &jsbObj);
@ -711,138 +710,68 @@ void js_remove_object_root(JS::HandleValue target)
}
JSCallbackWrapper::JSCallbackWrapper()
: _cppOwner(nullptr)
: _jsCallback(nullptr)
, _jsThisObj(nullptr)
, _extraData(nullptr)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedObject root(cx);
get_or_create_js_obj("jsb._root", &root);
JS::RootedValue valRoot(cx, OBJECT_TO_JSVAL(root));
_owner = valRoot;
}
JSCallbackWrapper::JSCallbackWrapper(JS::HandleValue owner)
: _cppOwner(nullptr)
{
_owner = owner;
JS::RootedObject ownerObj(ScriptingCore::getInstance()->getGlobalContext(), owner.toObjectOrNull());
js_proxy *t = jsb_get_js_proxy(ownerObj);
if (t) {
_cppOwner = t->ptr;
}
}
JSCallbackWrapper::~JSCallbackWrapper()
{
ScriptingCore* sc = ScriptingCore::getInstance();
JSContext* cx = sc->getGlobalContext();
JSAutoCompartment(cx, sc->getGlobalObject());
JS::RootedValue ownerVal(cx, _owner);
if (sc->getFinalizing() || ownerVal.isNullOrUndefined())
{
return;
}
js_proxy *t;
if (_cppOwner != nullptr)
{
JS::RootedObject ownerObj(cx, ownerVal.toObjectOrNull());
t = jsb_get_js_proxy(ownerObj);
// Owner already released, no need to do the following release anymore, gc will take care of everything
if (t == nullptr || _cppOwner != t->ptr)
{
return;
}
}
JS::RootedValue target(cx, _jsCallback);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
target.set(_jsThisObj);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
target.set(_extraData);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
CC_SAFE_DELETE(_jsCallback);
CC_SAFE_DELETE(_jsThisObj);
CC_SAFE_DELETE(_extraData);
}
void JSCallbackWrapper::setJSCallbackFunc(JS::HandleValue func) {
if (!func.isNullOrUndefined())
{
void JSCallbackWrapper::setJSCallbackFunc(JS::HandleValue func)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
JSAutoCompartment(cx, &ownerVal.toObject());
JS::RootedValue target(cx, _jsCallback);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(ownerVal, func);
}
_jsCallback = func;
}
CC_SAFE_DELETE(_jsCallback);
_jsCallback = new (std::nothrow) JS::PersistentRootedValue(cx, func);
}
void JSCallbackWrapper::setJSCallbackThis(JS::HandleValue thisObj) {
if (!thisObj.isNullOrUndefined())
{
void JSCallbackWrapper::setJSCallbackThis(JS::HandleValue thisObj)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
JSAutoCompartment(cx, &ownerVal.toObject());
JS::RootedValue target(cx, _jsThisObj);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(ownerVal, thisObj);
}
_jsThisObj = thisObj;
}
CC_SAFE_DELETE(_jsThisObj);
_jsThisObj = new (std::nothrow) JS::PersistentRootedValue(cx, thisObj);
}
void JSCallbackWrapper::setJSExtraData(JS::HandleValue data) {
if (!data.isNullOrUndefined())
{
void JSCallbackWrapper::setJSExtraData(JS::HandleValue data)
{
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
JS::RootedValue ownerVal(cx, _owner);
if (!ownerVal.isNullOrUndefined())
{
JSAutoCompartment(cx, &ownerVal.toObject());
JS::RootedValue target(cx, _extraData);
if (!target.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, target);
}
js_add_object_reference(ownerVal, data);
}
_extraData = data;
}
CC_SAFE_DELETE(_extraData);
_extraData = new (std::nothrow) JS::PersistentRootedValue(cx, data);
}
const jsval JSCallbackWrapper::getJSCallbackFunc() const
{
return _jsCallback;
if (_jsCallback != nullptr)
{
return _jsCallback->get();
}
return JS::NullValue();
}
const jsval JSCallbackWrapper::getJSCallbackThis() const
{
return _jsThisObj;
if (_jsThisObj != nullptr)
{
return _jsThisObj->get();
}
return JS::NullValue();
}
const jsval JSCallbackWrapper::getJSExtraData() const
{
return _extraData;
if (_extraData != nullptr)
{
return _extraData->get();
}
return JS::NullValue();
}
// cc.CallFunc.create( func, this, [data])
@ -858,7 +787,7 @@ static bool js_callFunc(JSContext *cx, uint32_t argc, jsval *vp)
JS::RootedObject jsobj(cx, jsb_ref_create_jsobject(cx, ret, typeClass, "cocos2d::CallFuncN"));
JS::RootedValue retVal(cx, OBJECT_TO_JSVAL(jsobj));
std::shared_ptr<JSCallbackWrapper> tmpCobj(new JSCallbackWrapper(retVal));
std::shared_ptr<JSCallbackWrapper> tmpCobj(new JSCallbackWrapper());
JS::RootedValue callback(cx, args.get(0));
tmpCobj->setJSCallbackFunc(callback);
@ -876,7 +805,13 @@ static bool js_callFunc(JSContext *cx, uint32_t argc, jsval *vp)
bool ok = ret->initWithFunction([=](Node* sender){
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedValue jsvalThis(cx, tmpCobj->getJSCallbackThis());
JS::RootedObject thisObj(cx, jsvalThis.toObjectOrNull());
JS::RootedObject thisObj(cx);
if (jsvalThis.isObject())
{
thisObj.set(jsvalThis.toObjectOrNull());
}
JS::RootedValue jsvalCallback(cx, tmpCobj->getJSCallbackFunc());
JS::RootedValue jsvalExtraData(cx, tmpCobj->getJSExtraData());
@ -930,7 +865,7 @@ bool js_cocos2dx_CallFunc_initWithFunction(JSContext *cx, uint32_t argc, jsval *
CallFuncN *action = (cocos2d::CallFuncN *)(proxy ? proxy->ptr : nullptr);
JSB_PRECONDITION2(action, cx, false, "Invalid Native Object");
std::shared_ptr<JSCallbackWrapper> tmpCobj(new JSCallbackWrapper(args.thisv()));
std::shared_ptr<JSCallbackWrapper> tmpCobj(new JSCallbackWrapper());
JS::RootedValue callback(cx, args.get(0));
tmpCobj->setJSCallbackFunc(callback);
@ -980,24 +915,20 @@ bool js_cocos2dx_CallFunc_initWithFunction(JSContext *cx, uint32_t argc, jsval *
}
JSScheduleWrapper::JSScheduleWrapper()
: JSCallbackWrapper()
, _pTarget(nullptr)
: _pTarget(nullptr)
, _priority(0)
, _isUpdateSchedule(false)
, _pPureJSTarget(nullptr)
{
_pPureJSTarget = nullptr;
}
JSScheduleWrapper::JSScheduleWrapper(JS::HandleValue owner)
: JSCallbackWrapper(owner)
, _pTarget(nullptr)
, _priority(0)
, _isUpdateSchedule(false)
JSScheduleWrapper::~JSScheduleWrapper()
{
_pPureJSTarget = nullptr;
CC_SAFE_DELETE(_pPureJSTarget);
}
void JSScheduleWrapper::setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target) {
void JSScheduleWrapper::setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target)
{
do {
JSObject* jsfunc = sched.toObjectOrNull();
auto targetArray = getTargetForSchedule(sched);
@ -1016,14 +947,14 @@ void JSScheduleWrapper::setTargetForSchedule(JS::HandleValue sched, JSScheduleWr
} while(0);
}
JSBinding::Array* JSScheduleWrapper::getTargetForSchedule(JS::HandleValue sched) {
JSBinding::Array* JSScheduleWrapper::getTargetForSchedule(JS::HandleValue sched)
{
schedFunc_proxy_t *t = nullptr;
JSObject *o = sched.toObjectOrNull();
HASH_FIND_PTR(_schedFunc_target_ht, &o, t);
return t != nullptr ? t->targets : nullptr;
}
void JSScheduleWrapper::setTargetForJSObject(JS::HandleObject jsTargetObj, JSScheduleWrapper *target)
{
auto targetArray = getTargetForJSObject(jsTargetObj);
@ -1323,12 +1254,14 @@ void JSScheduleWrapper::setTarget(Ref* pTarget)
void JSScheduleWrapper::setPureJSTarget(JS::HandleObject pPureJSTarget)
{
_pPureJSTarget = pPureJSTarget;
JSContext* cx = ScriptingCore::getInstance()->getGlobalContext();
CC_SAFE_DELETE(_pPureJSTarget);
_pPureJSTarget = new JS::PersistentRootedObject(cx, pPureJSTarget);
}
JSObject* JSScheduleWrapper::getPureJSTarget()
{
return _pPureJSTarget;
return _pPureJSTarget->get();
}
void JSScheduleWrapper::setPriority(int priority)
@ -1467,7 +1400,7 @@ bool js_CCNode_scheduleOnce(JSContext *cx, uint32_t argc, jsval *vp)
if (!bFound)
{
tmpCobj = new (std::nothrow) JSScheduleWrapper(thisValue);
tmpCobj = new (std::nothrow) JSScheduleWrapper();
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(thisValue);
tmpCobj->setJSCallbackFunc(args.get(0));
@ -1565,7 +1498,7 @@ bool js_CCNode_schedule(JSContext *cx, uint32_t argc, jsval *vp)
if (!bFound)
{
tmpCobj = new (std::nothrow) JSScheduleWrapper(thisValue);
tmpCobj = new (std::nothrow) JSScheduleWrapper();
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(thisValue);
tmpCobj->setJSCallbackFunc(args.get(0));
@ -1641,7 +1574,7 @@ bool js_cocos2dx_CCNode_scheduleUpdateWithPriority(JSContext *cx, uint32_t argc,
if (!bFound)
{
tmpCobj = new (std::nothrow) JSScheduleWrapper(JS::NullHandleValue);
tmpCobj = new (std::nothrow) JSScheduleWrapper();
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(thisValue);
tmpCobj->setJSCallbackFunc(jsUpdateFunc);
@ -1744,7 +1677,7 @@ bool js_cocos2dx_CCNode_scheduleUpdate(JSContext *cx, uint32_t argc, jsval *vp)
if (!bFound)
{
tmpCobj = new (std::nothrow) JSScheduleWrapper(JS::NullHandleValue);
tmpCobj = new (std::nothrow) JSScheduleWrapper();
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(thisValue);
tmpCobj->setJSCallbackFunc(jsUpdateFunc);
@ -1861,7 +1794,7 @@ bool js_CCScheduler_scheduleUpdateForTarget(JSContext *cx, uint32_t argc, jsval
if (!bFound)
{
tmpCObj = new (std::nothrow) JSScheduleWrapper(args.thisv());
tmpCObj = new (std::nothrow) JSScheduleWrapper();
tmpCObj->autorelease();
tmpCObj->setJSCallbackThis(args.get(0));
tmpCObj->setJSCallbackFunc(jsUpdateFunc);
@ -1989,7 +1922,7 @@ bool js_CCScheduler_scheduleCallbackForTarget(JSContext *cx, uint32_t argc, jsva
if (!bFound)
{
tmpCObj = new (std::nothrow) JSScheduleWrapper(args.thisv());
tmpCObj = new (std::nothrow) JSScheduleWrapper();
tmpCObj->autorelease();
tmpCObj->setJSCallbackThis(args.get(0));
tmpCObj->setJSCallbackFunc(args.get(1));
@ -2660,6 +2593,9 @@ bool js_cocos2dx_ActionInterval_repeat(JSContext *cx, uint32_t argc, jsval *vp)
cocos2d::Repeat* action = new (std::nothrow) cocos2d::Repeat;
action->initWithAction(cobj, timesInt);
#if !CC_ENABLE_GC_FOR_NATIVE_OBJECTS
action->autorelease();
#endif
jsb_ref_rebind(cx, obj, proxy, cobj, action, "cocos2d::Repeat");
args.rval().set(OBJECT_TO_JSVAL(obj));
@ -2681,7 +2617,9 @@ bool js_cocos2dx_ActionInterval_repeatForever(JSContext *cx, uint32_t argc, jsva
if (argc == 0) {
cocos2d::RepeatForever* action = new (std::nothrow) cocos2d::RepeatForever;
action->initWithAction(cobj);
#if !CC_ENABLE_GC_FOR_NATIVE_OBJECTS
action->autorelease();
#endif
jsb_ref_rebind(cx, jsobj, proxy, cobj, action, "cocos2d::RepeatForever");
args.rval().set(OBJECT_TO_JSVAL(jsobj));
return true;
@ -2712,6 +2650,9 @@ bool js_cocos2dx_ActionInterval_speed(JSContext *cx, uint32_t argc, jsval *vp)
cocos2d::Speed* action = new (std::nothrow) cocos2d::Speed;
action->initWithAction(cobj, speed);
#if !CC_ENABLE_GC_FOR_NATIVE_OBJECTS
action->autorelease();
#endif
jsb_ref_rebind(cx, obj, proxy, cobj, action, "cocos2d::Speed");
args.rval().set(OBJECT_TO_JSVAL(obj));
@ -2762,6 +2703,12 @@ enum ACTION_TAG {
bool js_cocos2dx_ActionInterval_easing(JSContext *cx, uint32_t argc, jsval *vp)
{
if (argc == 0)
{
JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedObject jsobj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(jsobj);
@ -2772,19 +2719,19 @@ bool js_cocos2dx_ActionInterval_easing(JSContext *cx, uint32_t argc, jsval *vp)
JS::RootedObject tmp(cx);
JS::RootedValue jsTag(cx);
JS::RootedValue jsParam(cx);
double tag;
double parameter;
double tag = 0.0;
double parameter = 0.0;
for (uint32_t i = 0; i < argc; i++)
do
{
JS::RootedValue vpi(cx, args.get(i));
JS::RootedValue vpi(cx, args[0]);
bool ok = vpi.isObject() &&
JS_ValueToObject(cx, vpi, &tmp) &&
JS_GetProperty(cx, tmp, "tag", &jsTag) &&
JS::ToNumber(cx, jsTag, &tag);
JS_GetProperty(cx, tmp, "param", &jsParam) && JS::ToNumber(cx, jsParam, &parameter);
bool hasParam = (parameter == parameter);
if (!ok) continue;
if (!ok) break;
ok = true;
if (tag == EASE_IN)
@ -3003,7 +2950,7 @@ bool js_cocos2dx_ActionInterval_easing(JSContext *cx, uint32_t argc, jsval *vp)
ok &= JS::ToNumber(cx, jsParam3, &parameter3);
ok &= JS_GetProperty(cx, tmp, "param4", &jsParam4);
ok &= JS::ToNumber(cx, jsParam4, &parameter4);
if (!ok) continue;
if (!ok) break;
auto tmpaction = new (std::nothrow) cocos2d::EaseBezierAction;
tmpaction->initWithAction(oldAction);
@ -3011,14 +2958,19 @@ bool js_cocos2dx_ActionInterval_easing(JSContext *cx, uint32_t argc, jsval *vp)
newAction = tmpaction;
}
else
continue;
{
break;
}
if (!ok || !newAction) {
JS_ReportError(cx, "js_cocos2dx_ActionInterval_easing : Invalid action: At least one action was expecting parameter");
return false;
}
}
} while (false);
#if !CC_ENABLE_GC_FOR_NATIVE_OBJECTS
newAction->autorelease();
#endif
// Unbind existing proxy binding with cobj, and rebind with the new action
jsb_ref_rebind(cx, jsobj, proxy, oldAction, newAction, "cocos2d::EaseAction");

View File

@ -158,8 +158,8 @@ void register_cocos2dx_js_core(JSContext* cx, JS::HandleObject obj);
class JSCallbackWrapper: public cocos2d::Ref {
public:
JSCallbackWrapper();
JSCallbackWrapper(JS::HandleValue owner);
virtual ~JSCallbackWrapper();
void setJSCallbackFunc(JS::HandleValue callback);
void setJSCallbackThis(JS::HandleValue thisObj);
void setJSExtraData(JS::HandleValue data);
@ -168,19 +168,17 @@ public:
const jsval getJSCallbackThis() const;
const jsval getJSExtraData() const;
protected:
JS::Heap<JS::Value> _owner;
JS::Heap<JS::Value> _jsCallback;
JS::Heap<JS::Value> _jsThisObj;
JS::Heap<JS::Value> _extraData;
void* _cppOwner;
JS::PersistentRootedValue* _jsCallback;
JS::PersistentRootedValue* _jsThisObj;
JS::PersistentRootedValue* _extraData;
};
class JSScheduleWrapper: public JSCallbackWrapper {
class JSScheduleWrapper: public JSCallbackWrapper
{
public:
JSScheduleWrapper();
JSScheduleWrapper(JS::HandleValue owner);
virtual ~JSScheduleWrapper();
static void setTargetForSchedule(JS::HandleValue sched, JSScheduleWrapper *target);
static JSBinding::Array* getTargetForSchedule(JS::HandleValue sched);
@ -216,7 +214,7 @@ public:
protected:
Ref* _pTarget;
JS::Heap<JSObject*> _pPureJSTarget;
JS::PersistentRootedObject* _pPureJSTarget;
int _priority;
bool _isUpdateSchedule;
};

View File

@ -29,7 +29,7 @@
class JSCCBAnimationWrapper: public JSCallbackWrapper
{
public:
JSCCBAnimationWrapper(JS::HandleValue owner) : JSCallbackWrapper(owner) {}
JSCCBAnimationWrapper() {}
void animationCompleteCallback()
{

View File

@ -99,7 +99,7 @@ bool js_cocos2dx_CCBAnimationManager_animationCompleteCallback(JSContext *cx, ui
js_proxy_t *p = jsb_get_js_proxy(obj);
cocosbuilder::CCBAnimationManager *node = (cocosbuilder::CCBAnimationManager *)(p ? p->ptr : NULL);
JSCCBAnimationWrapper *tmpCobj = new (std::nothrow) JSCCBAnimationWrapper(args.thisv());
JSCCBAnimationWrapper *tmpCobj = new (std::nothrow) JSCCBAnimationWrapper();
tmpCobj->autorelease();
tmpCobj->setJSCallbackThis(args.get(0));

View File

@ -28,7 +28,7 @@
class JSArmatureWrapper: public JSCallbackWrapper {
public:
JSArmatureWrapper(JS::HandleValue owner) : JSCallbackWrapper(owner) {};
JSArmatureWrapper(){};
void movementCallbackFunc(cocostudio::Armature *armature, cocostudio::MovementEventType movementType, const std::string& movementID);
void frameCallbackFunc(cocostudio::Bone *bone, const std::string& evt, int originFrameIndex, int currentFrameIndex);
@ -117,7 +117,7 @@ static bool js_cocos2dx_ArmatureAnimation_setMovementEventCallFunc(JSContext *cx
return true;
}
else if (argc == 1 || argc == 2) {
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper(args.thisv());
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper();
tmpObj->autorelease();
auto userDict = static_cast<JSBinding::DictionaryRef*>(cobj->getUserObject());
@ -164,7 +164,7 @@ static bool js_cocos2dx_ArmatureAnimation_setFrameEventCallFunc(JSContext *cx, u
return true;
}
else if (argc == 1 || argc == 2) {
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper(args.thisv());
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper();
tmpObj->autorelease();
auto dict = static_cast<JSBinding::DictionaryRef*>(cobj->getUserObject());
@ -206,7 +206,7 @@ static bool jsb_Animation_addArmatureFileInfoAsyncCallFunc(JSContext *cx, uint32
JSB_PRECONDITION2( cobj, cx, false, "Invalid Native Object");
if (argc == 3) {
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper(args.thisv());
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper();
tmpObj->autorelease();
tmpObj->setJSCallbackFunc(args.get(1));
@ -221,7 +221,7 @@ static bool jsb_Animation_addArmatureFileInfoAsyncCallFunc(JSContext *cx, uint32
}
if(argc == 5){
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper(args.thisv());
JSArmatureWrapper *tmpObj = new (std::nothrow) JSArmatureWrapper();
tmpObj->autorelease();
tmpObj->setJSCallbackFunc(args.get(3));

View File

@ -31,8 +31,10 @@
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "network/CCDownloader.h"
#include "renderer/CCTextureCache.h"
#include "renderer/CCTextureCube.h"
#include "renderer/CCTexture2D.h"
USING_NS_CC;
USING_NS_CC_EXT;
@ -301,7 +303,6 @@ private:
jsval dataVal = OBJECT_TO_JSVAL(p->obj);
JS::RootedObject obj(cx, _JSTableViewDataSource);
JSAutoCompartment ac(cx, obj);
if (JS_HasProperty(cx, obj, jsFunctionName.c_str(), &hasAction) && hasAction)
{
@ -334,7 +335,6 @@ private:
dataVal[1] = ssize_to_jsval(cx,idx);
JS::RootedObject obj(cx, _JSTableViewDataSource);
JSAutoCompartment ac(cx, obj);
if (JS_HasProperty(cx, obj, jsFunctionName.c_str(), &hasAction) && hasAction)
{
@ -813,10 +813,6 @@ bool js_cocos2dx_extension_EventListenerAssetsManagerEx_create(JSContext *cx, ui
if (ret) {
JS::RootedObject jsobj(cx, js_get_or_create_jsobject<cocos2d::extension::EventListenerAssetsManagerEx>(cx, ret));
jsret = OBJECT_TO_JSVAL(jsobj);
if (wrapper)
{
wrapper->setOwner(cx, jsret);
}
} else {
jsret = JS::NullValue();
}
@ -827,50 +823,54 @@ bool js_cocos2dx_extension_EventListenerAssetsManagerEx_create(JSContext *cx, ui
return false;
}
__JSDownloaderDelegator::__JSDownloaderDelegator(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleObject callback)
class JSDownloaderDelegator : cocos2d::Ref
{
public:
void download();
static JSDownloaderDelegator *create(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleValue callback);
protected:
JSDownloaderDelegator(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleValue callback);
~JSDownloaderDelegator();
void startDownload();
private:
void onSuccess(cocos2d::Texture2D *tex);
void onError();
std::shared_ptr<cocos2d::network::Downloader> _downloader;
std::string _url;
JSContext *_cx;
JS::PersistentRootedValue* _jsCallback;
JS::PersistentRootedObject* _obj;
};
JSDownloaderDelegator::JSDownloaderDelegator(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleValue callback)
: _cx(cx)
, _url(url)
{
_obj = obj;
_jsCallback = callback;
JS::RootedValue target(cx, OBJECT_TO_JSVAL(obj));
if (!target.isNullOrUndefined())
{
js_add_object_root(target);
}
target.set(OBJECT_TO_JSVAL(callback));
if (!target.isNullOrUndefined())
{
js_add_object_root(target);
}
_obj = new (std::nothrow) JS::PersistentRootedObject(cx, obj);
_jsCallback = new (std::nothrow) JS::PersistentRootedValue(cx, callback);
}
__JSDownloaderDelegator::~__JSDownloaderDelegator()
JSDownloaderDelegator::~JSDownloaderDelegator()
{
JS::RootedValue target(_cx, OBJECT_TO_JSVAL(_obj));
if (!target.isNullOrUndefined())
{
js_remove_object_root(target);
}
target.set(OBJECT_TO_JSVAL(_jsCallback));
if (!target.isNullOrUndefined())
{
js_remove_object_root(target);
}
CC_SAFE_DELETE(_obj);
CC_SAFE_DELETE(_jsCallback);
_downloader->onTaskError = (nullptr);
_downloader->onDataTaskSuccess = (nullptr);
_downloader->onTaskError = nullptr;
_downloader->onDataTaskSuccess = nullptr;
}
__JSDownloaderDelegator *__JSDownloaderDelegator::create(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleObject callback)
JSDownloaderDelegator *JSDownloaderDelegator::create(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleValue callback)
{
__JSDownloaderDelegator *delegate = new (std::nothrow) __JSDownloaderDelegator(cx, obj, url, callback);
JSDownloaderDelegator *delegate = new (std::nothrow) JSDownloaderDelegator(cx, obj, url, callback);
delegate->autorelease();
return delegate;
}
void __JSDownloaderDelegator::startDownload()
void JSDownloaderDelegator::startDownload()
{
if (auto texture = Director::getInstance()->getTextureCache()->getTextureForKey(_url))
{
@ -918,43 +918,29 @@ void __JSDownloaderDelegator::startDownload()
}
}
void __JSDownloaderDelegator::download()
void JSDownloaderDelegator::download()
{
retain();
startDownload();
}
void __JSDownloaderDelegator::downloadAsync()
void JSDownloaderDelegator::onError()
{
retain();
auto t = std::thread(&__JSDownloaderDelegator::startDownload, this);
t.detach();
}
void __JSDownloaderDelegator::onError()
{
Director::getInstance()->getScheduler()->performFunctionInCocosThread([this]
{
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback));
JS::RootedValue callback(_cx, *_jsCallback);
if (!callback.isNull()) {
JS::RootedObject global(_cx, ScriptingCore::getInstance()->getGlobalObject());
JSAutoCompartment ac(_cx, global);
jsval succeed = BOOLEAN_TO_JSVAL(false);
JS::RootedValue retval(_cx);
JS_CallFunctionValue(_cx, global, callback, JS::HandleValueArray::fromMarkedLocation(1, &succeed), &retval);
}
release();
});
}
void __JSDownloaderDelegator::onSuccess(Texture2D *tex)
void JSDownloaderDelegator::onSuccess(Texture2D *tex)
{
CCASSERT(tex, "__JSDownloaderDelegator::onSuccess must make sure tex not null!");
//Director::getInstance()->getScheduler()->performFunctionInCocosThread([this, tex]
{
CCASSERT(tex, "JSDownloaderDelegator::onSuccess must make sure tex not null!");
JS::RootedObject global(_cx, ScriptingCore::getInstance()->getGlobalObject());
JSAutoCompartment ac(_cx, global);
jsval valArr[2];
if (tex)
@ -969,14 +955,13 @@ void __JSDownloaderDelegator::onSuccess(Texture2D *tex)
valArr[1] = JSVAL_NULL;
}
JS::RootedValue callback(_cx, OBJECT_TO_JSVAL(_jsCallback));
JS::RootedValue callback(_cx, *_jsCallback);
if (!callback.isNull())
{
JS::RootedValue retval(_cx);
JS_CallFunctionValue(_cx, global, callback, JS::HandleValueArray::fromMarkedLocation(2, valArr), &retval);
}
release();
}//);
}
// jsb.loadRemoteImg(url, function(succeed, result) {})
@ -989,10 +974,8 @@ bool js_load_remote_image(JSContext *cx, uint32_t argc, jsval *vp)
std::string url;
bool ok = jsval_to_std_string(cx, args.get(0), &url);
JSB_PRECONDITION2(ok, cx, false, "js_load_remote_image : Error processing arguments");
JS::RootedObject callback(cx, args.get(1).toObjectOrNull());
__JSDownloaderDelegator *delegate = __JSDownloaderDelegator::create(cx, obj, url, callback);
delegate->downloadAsync();
JSDownloaderDelegator *delegate = JSDownloaderDelegator::create(cx, obj, url, args[1]);
delegate->download();
args.rval().setUndefined();
return true;

View File

@ -26,32 +26,6 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "network/CCDownloader.h"
#include "renderer/CCTexture2D.h"
class __JSDownloaderDelegator : cocos2d::Ref
{
public:
void downloadAsync();
void download();
static __JSDownloaderDelegator *create(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleObject callback);
protected:
__JSDownloaderDelegator(JSContext *cx, JS::HandleObject obj, const std::string &url, JS::HandleObject callback);
~__JSDownloaderDelegator();
void startDownload();
private:
void onSuccess(cocos2d::Texture2D *tex);
void onError();
std::shared_ptr<cocos2d::network::Downloader> _downloader;
std::string _url;
JSContext *_cx;
JS::Heap<JSObject*> _jsCallback;
JS::Heap<JSObject*> _obj;
};
void register_all_cocos2dx_extension_manual(JSContext* cx, JS::HandleObject global);

View File

@ -116,9 +116,7 @@ JSAutoCompartment ac(cx, obj)
#define JSB_ENSURE_AUTOCOMPARTMENT(cx, obj)
#endif
#define JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET \
JSAutoCompartment __jsb_ac(ScriptingCore::getInstance()->getGlobalContext(), ScriptingCore::getInstance()->getGlobalObject());
#define JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
/** @def JSB_INCLUDE_SYSTEM
Whether or not it should include bindings for system components like LocalStorage

View File

@ -141,12 +141,12 @@ void jsb_del_c_proxy_for_jsobject( JSObject *jsobj )
CCASSERT(proxy, "Invalid proxy for JSObject");
JS_SetPrivate(jsobj, NULL);
free(proxy);
delete(proxy);
}
void jsb_set_c_proxy_for_jsobject( JSObject *jsobj, void *handle, unsigned long flags)
{
struct jsb_c_proxy_s *proxy = (struct jsb_c_proxy_s*) malloc(sizeof(*proxy));
struct jsb_c_proxy_s *proxy = new (std::nothrow) (struct jsb_c_proxy_s);
CCASSERT(proxy, "No memory for proxy");
proxy->handle = handle;

View File

@ -107,80 +107,23 @@ const char* JSStringWrapper::get()
// JSFunctionWrapper
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval)
: _cppOwner(nullptr)
, _cx(cx)
: _cx(cx)
{
_jsthis = jsthis;
_fval = fval;
_jsthis = new (std::nothrow) JS::PersistentRootedObject(cx, jsthis);
_fval = new (std::nothrow) JS::PersistentRootedValue(cx, fval);
}
JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval, JS::HandleValue owner)
: _cppOwner(nullptr)
, _cx(cx)
: _cx(cx)
{
_jsthis = jsthis;
_fval = fval;
setOwner(cx, JS::RootedValue(cx, owner));
_jsthis = new (std::nothrow) JS::PersistentRootedObject(cx, jsthis);
_fval = new (std::nothrow) JS::PersistentRootedValue(cx, fval);
}
JSFunctionWrapper::~JSFunctionWrapper()
{
ScriptingCore* sc = ScriptingCore::getInstance();
JSContext* cx = sc->getGlobalContext();
JSAutoCompartment(cx, sc->getGlobalObject());
JS::RootedValue ownerVal(_cx, _owner);
if (sc->getFinalizing() || ownerVal.isNullOrUndefined())
{
return;
}
if (_cppOwner != nullptr)
{
JS::RootedObject ownerObj(cx, ownerVal.toObjectOrNull());
js_proxy *t = jsb_get_js_proxy(ownerObj);
// JS object already released, no need to do the following release anymore, gc will take care of everything
if (t == nullptr || _cppOwner != t->ptr)
{
return;
}
}
JS::RootedValue thisVal(_cx, OBJECT_TO_JSVAL(_jsthis));
if (!thisVal.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, thisVal);
}
JS::RootedValue funcVal(_cx, _fval);
if (!funcVal.isNullOrUndefined())
{
js_remove_object_reference(ownerVal, funcVal);
}
}
void JSFunctionWrapper::setOwner(JSContext* cx, JS::HandleValue owner)
{
JSAutoCompartment(cx, ScriptingCore::getInstance()->getGlobalObject());
JS::RootedValue ownerVal(cx, owner);
if (!owner.isNullOrUndefined())
{
_owner = owner;
JS::RootedObject ownerObj(cx, owner.toObjectOrNull());
js_proxy *t = jsb_get_js_proxy(ownerObj);
if (t) {
_cppOwner = t->ptr;
}
JS::RootedValue thisVal(cx, OBJECT_TO_JSVAL(_jsthis));
if (!thisVal.isNullOrUndefined())
{
js_add_object_reference(ownerVal, thisVal);
}
JS::RootedValue funcVal(cx, _fval);
if (!funcVal.isNullOrUndefined())
{
js_add_object_reference(ownerVal, funcVal);
}
}
CC_SAFE_DELETE(_jsthis);
CC_SAFE_DELETE(_fval);
}
bool JSFunctionWrapper::invoke(unsigned int argc, jsval *argv, JS::MutableHandleValue rval)
@ -190,11 +133,7 @@ bool JSFunctionWrapper::invoke(unsigned int argc, jsval *argv, JS::MutableHandle
bool JSFunctionWrapper::invoke(JS::HandleValueArray args, JS::MutableHandleValue rval)
{
JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
JS::RootedObject thisObj(_cx, _jsthis);
JS::RootedValue fval(_cx, _fval);
return JS_CallFunctionValue(_cx, thisObj, fval, args, rval);
return JS_CallFunctionValue(_cx, *_jsthis, *_fval, args, rval);
}
static Color3B getColorFromJSObject(JSContext *cx, JS::HandleObject colorObject)

View File

@ -82,16 +82,13 @@ public:
JSFunctionWrapper(JSContext* cx, JS::HandleObject jsthis, JS::HandleValue fval, JS::HandleValue owner);
~JSFunctionWrapper();
void setOwner(JSContext* cx, JS::HandleValue owner);
bool invoke(unsigned int argc, jsval *argv, JS::MutableHandleValue rval);
bool invoke(JS::HandleValueArray args, JS::MutableHandleValue rval);
private:
JSContext *_cx;
JS::Heap<JSObject*> _jsthis;
JS::Heap<JS::Value> _fval;
JS::Heap<JS::Value> _owner;
void* _cppOwner;
JS::PersistentRootedObject* _jsthis;
JS::PersistentRootedValue* _fval;
private:
CC_DISALLOW_COPY_AND_ASSIGN(JSFunctionWrapper);
};

View File

@ -202,10 +202,6 @@ bool js_EventListenerAcceleration_create(JSContext *cx, uint32_t argc, jsval *vp
auto ret = EventListenerAcceleration::create(arg0);
JS::RootedValue jsret(cx, OBJECT_TO_JSVAL(js_get_or_create_jsobject<EventListenerAcceleration>(cx, ret)));
if (wrapper)
{
wrapper->setOwner(cx, jsret);
}
args.rval().set(jsret);
return true;
}
@ -275,10 +271,6 @@ bool js_EventListenerCustom_create(JSContext *cx, uint32_t argc, jsval *vp)
auto ret = EventListenerCustom::create(arg0, arg1);
JS::RootedValue jsret(cx, OBJECT_TO_JSVAL(js_get_or_create_jsobject<EventListenerCustom>(cx, ret)));
if (wrapper)
{
wrapper->setOwner(cx, jsret);
}
args.rval().set(jsret);
return true;
}

View File

@ -1035,7 +1035,6 @@ void MinXmlHttpRequest::_notify(JS::HandleObject callback, JS::HandleValueArray
if (callback)
{
JS::RootedObject obj(_cx, p->obj);
JSAutoCompartment ac(_cx, obj);
//JS_IsExceptionPending(cx) && JS_ReportPendingException(cx);
JS::RootedValue callbackVal(_cx, OBJECT_TO_JSVAL(callback));
JS::RootedValue out(_cx);

View File

@ -2329,6 +2329,11 @@ var Issue1305 = ActionsDemo.extend({
},
onExit:function () {
this._super();
if (this._spriteTmp)
{
this._spriteTmp.release();
this._spriteTmp = null;
}
},
onLog:function (pSender) {
cc.log("This message SHALL ONLY appear when the sprite is added to the scene, NOT BEFORE");
@ -2336,8 +2341,12 @@ var Issue1305 = ActionsDemo.extend({
onAddSprite:function (dt) {
this._spriteTmp.x = 250;
this._spriteTmp.y = 250;
if (this._spriteTmp)
{
this.addChild(this._spriteTmp);
this._spriteTmp.release();
this._spriteTmp = null;
}
},
title:function () {
return "Issue 1305";