mirror of https://github.com/axmolengine/axmol.git
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:
parent
8f1459b8ef
commit
b2ecbca549
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ¶meter);
|
||||
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, ¶meter3);
|
||||
ok &= JS_GetProperty(cx, tmp, "param4", &jsParam4);
|
||||
ok &= JS::ToNumber(cx, jsParam4, ¶meter4);
|
||||
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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
class JSCCBAnimationWrapper: public JSCallbackWrapper
|
||||
{
|
||||
public:
|
||||
JSCCBAnimationWrapper(JS::HandleValue owner) : JSCallbackWrapper(owner) {}
|
||||
JSCCBAnimationWrapper() {}
|
||||
|
||||
void animationCompleteCallback()
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue