diff --git a/native/cocos/bindings/jswrapper/jsvm/Object.cpp b/native/cocos/bindings/jswrapper/jsvm/Object.cpp index 25163543ae9..efbc39f984e 100644 --- a/native/cocos/bindings/jswrapper/jsvm/Object.cpp +++ b/native/cocos/bindings/jswrapper/jsvm/Object.cpp @@ -36,18 +36,17 @@ namespace se { std::unique_ptr> __objectMap; // Currently, the value `void*` is always nullptr -std::set Object::objBaseSet = {}; -bool Object::restarting = false; + Object::Object() {} Object::~Object() { - if(restarting) { - objBaseSet.insert(this); - } if (__objectMap) { __objectMap->erase(this); } + + delete _privateObject; + _privateObject = nullptr; } Object* Object::createObjectWithClass(Class* cls) { @@ -652,7 +651,6 @@ std::string Object::toString() const { } void Object::root() { - JSVM_Status status; if (_rootCount == 0) { uint32_t result = 0; _objRef.incRef(_env); @@ -661,7 +659,6 @@ void Object::root() { } void Object::unroot() { - JSVM_Status status; if (_rootCount > 0) { --_rootCount; if (_rootCount == 0) { @@ -704,37 +701,34 @@ void Object::weakCallback(JSVM_Env env, void* nativeObject, void* finalizeHint / } void* rawPtr = reinterpret_cast(finalizeHint)->_privateData; Object* seObj = reinterpret_cast(finalizeHint); - - auto it = objBaseSet.find(seObj); - if(it != objBaseSet.end()) { + if (seObj->_onCleaingPrivateData) { //called by cleanPrivateData, not release seObj; return; } - - if (seObj->_onCleaingPrivateData) { //called by cleanPrivateData, not release seObj; + if(!NativePtrToObjectMap::isValid()) { return; } if (seObj->_clearMappingInFinalizer && rawPtr != nullptr) { auto iter = NativePtrToObjectMap::find(rawPtr); if (iter != NativePtrToObjectMap::end()) { - if (seObj->_finalizeCb != nullptr) { - seObj->_finalizeCb(env, finalizeHint, finalizeHint); - } else { - assert(seObj->_getClass() != nullptr); - if (seObj->_getClass()->_getFinalizeFunction() != nullptr) { - seObj->_getClass()->_getFinalizeFunction()(env, finalizeHint, finalizeHint); - } - } - seObj->decRef(); NativePtrToObjectMap::erase(iter); } else { SE_LOGE("not find ptr in NativePtrToObjectMap"); } } + + if (seObj->_finalizeCb != nullptr) { + seObj->_finalizeCb(env, finalizeHint, finalizeHint); + } else { + assert(seObj->_getClass() != nullptr); + if (seObj->_getClass()->_getFinalizeFunction() != nullptr) { + seObj->_getClass()->_getFinalizeFunction()(env, finalizeHint, finalizeHint); + } + } + seObj->decRef(); } } void Object::setup() { - restarting = false; __objectMap = std::make_unique>(); } @@ -749,11 +743,11 @@ void Object::cleanup() { obj = e.second; if (obj->_finalizeCb != nullptr) { - obj->_finalizeCb(ScriptEngine::getEnv(), nativeObj, nullptr); + obj->_finalizeCb(ScriptEngine::getEnv(), obj, nullptr); } else { if (obj->_getClass() != nullptr) { if (obj->_getClass()->_getFinalizeFunction() != nullptr) { - obj->_getClass()->_getFinalizeFunction()(ScriptEngine::getEnv(), nativeObj, nullptr); + obj->_getClass()->_getFinalizeFunction()(ScriptEngine::getEnv(), obj, nullptr); } } } diff --git a/native/cocos/bindings/jswrapper/jsvm/Object.h b/native/cocos/bindings/jswrapper/jsvm/Object.h index 4dd684d2c47..d43bbc528f1 100644 --- a/native/cocos/bindings/jswrapper/jsvm/Object.h +++ b/native/cocos/bindings/jswrapper/jsvm/Object.h @@ -117,12 +117,6 @@ class Object : public RefCounter { BIGINT64, BIGUINT64 }; - - static std::set objBaseSet; - static bool restarting; - static void resetBaseSet() { - objBaseSet.erase(objBaseSet.begin(), objBaseSet.end()); - } using BufferContentsFreeFunc = void (*)(void *contents, size_t byteLength, void *userData); diff --git a/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.cpp b/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.cpp index fc65e215511..1e705c820ab 100644 --- a/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.cpp +++ b/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.cpp @@ -138,17 +138,14 @@ SE_BIND_FUNC(JSB_console_assert) ScriptEngine *gSriptEngineInstance = nullptr; ScriptEngine::ScriptEngine() { - static bool initialized = false; - if (initialized) { - return; - } - JSVM_InitOptions initOptions; - memset(&initOptions, 0, sizeof(initOptions)); - OH_JSVM_Init(&initOptions); - initialized = true; + OH_JSVM_Init(nullptr); + gSriptEngineInstance = this; }; -ScriptEngine::~ScriptEngine() = default; +ScriptEngine::~ScriptEngine() { + cleanup(); + gSriptEngineInstance = nullptr; +}; void ScriptEngine::setFileOperationDelegate(const FileOperationDelegate &delegate) { _fileOperationDelegate = delegate; @@ -303,6 +300,21 @@ bool ScriptEngine::init() { Object *ScriptEngine::getGlobalObject() const { return _globalObj; } +void ScriptEngine::closeEngine() { + JSVM_Env env = _env; + _env = nullptr; + + JSVM_Status status; + NODE_API_CALL(status, env, OH_JSVM_CloseEnvScope(env, _envScope)); + NODE_API_CALL(status, env, OH_JSVM_DestroyEnv(env)); + NODE_API_CALL(status, env, OH_JSVM_CloseVMScope(_vm, _vmScope)); + NODE_API_CALL(status, env, OH_JSVM_DestroyVM(_vm)); + _envScope = nullptr; + env = nullptr; + _vmScope = nullptr; + _vm = nullptr; +} + bool ScriptEngine::start() { bool ok = true; if (!init()) { @@ -337,22 +349,25 @@ void ScriptEngine::cleanup() { if (!_isValid) { return; } - Object::restarting = true; - Object::resetBaseSet(); + SE_LOGD("ScriptEngine::cleanup begin ...\n"); _isInCleanup = true; - se::AutoHandleScope hs; + + //cc::events::ScriptEngine::broadcast(cc::ScriptEngineEvent::BEFORE_CLEANUP); + do{ + se::AutoHandleScope hs; for (const auto &hook : _beforeCleanupHookArray) { hook(); } + _beforeCleanupHookArray.clear(); }while (0); - _beforeCleanupHookArray.clear(); + SAFE_DEC_REF(_globalObj); Object::cleanup(); Class::cleanup(); - garbageCollect(); + __oldConsoleLog.setUndefined(); __oldConsoleDebug.setUndefined(); @@ -360,20 +375,8 @@ void ScriptEngine::cleanup() { __oldConsoleWarn.setUndefined(); __oldConsoleError.setUndefined(); __oldConsoleAssert.setUndefined(); + garbageCollect(); - JSVM_Env env = _env; - _env = nullptr; - - JSVM_Status status; - NODE_API_CALL(status, env, OH_JSVM_CloseEnvScope(env, _envScope)); - - NODE_API_CALL(status, env, OH_JSVM_DestroyEnv(env)); - NODE_API_CALL(status, env, OH_JSVM_CloseVMScope(_vm, _vmScope)); - NODE_API_CALL(status, env, OH_JSVM_DestroyVM(_vm)); - _envScope = nullptr; - env = nullptr; - _vmScope = nullptr; - _vm = nullptr; _globalObj = nullptr; _isValid = false; diff --git a/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.h b/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.h index c0f7d4b17a3..e46edd4196b 100644 --- a/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.h +++ b/native/cocos/bindings/jswrapper/jsvm/ScriptEngine.h @@ -77,6 +77,11 @@ class ScriptEngine { }; ScriptEngine(); ~ScriptEngine(); + /** + * @brief Shut down the JSVM engine, because cleanup doesn't destroy all objects immediately. + */ + void closeEngine(); + /** * @brief Sets the delegate for file operation. * @param delegate[in] The delegate instance for file operation. diff --git a/native/cocos/engine/Engine.cpp b/native/cocos/engine/Engine.cpp index 2497b0753a8..a5622e19e1f 100644 --- a/native/cocos/engine/Engine.cpp +++ b/native/cocos/engine/Engine.cpp @@ -207,6 +207,10 @@ void Engine::destroy() { if (cc::render::getRenderingModule()) { cc::render::Factory::destroy(cc::render::getRenderingModule()); } + #if(CC_PLATFORM == CC_PLATFORM_OPENHARMONY && SCRIPT_ENGINE_TYPE == SCRIPT_ENGINE_JSVM) + // When using JSVM, not all objects are destroyed during cleanup, so we need to close JSVM at the end. + _scriptEngine->closeEngine(); + #endif CC_SAFE_DESTROY_AND_DELETE(_gfxDevice); delete _fs;