From 2eef040720e5648b97b0101f11761ade693ac9fb Mon Sep 17 00:00:00 2001 From: EmixamPP Date: Tue, 2 Jul 2024 11:28:28 +0200 Subject: [PATCH 1/5] fix: memory leak on component unmounting reference and proxy to the components where preventing GC fix for #23 --- src/render/react/core/reconciler/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/render/react/core/reconciler/index.js b/src/render/react/core/reconciler/index.js index 0bdda57..5cf4786 100644 --- a/src/render/react/core/reconciler/index.js +++ b/src/render/react/core/reconciler/index.js @@ -53,7 +53,6 @@ const HostConfig = { workInProgress, uid, ); - instanceMap[uid] = instance; return instance; }, createTextInstance: ( @@ -124,12 +123,16 @@ const HostConfig = { commitTextUpdate(textInstance, oldText, newText) { textInstance.setText(newText); }, + detachDeletedInstance: (instance) => { + unRegistEvent(instance.uid); + instanceMap.delete(instance.uid); + instance.style = null; // Proxy preventing GC + }, removeChild(parent, child) { parent?.removeChild(child); - unRegistEvent(child.uid); - delete instanceMap[child.uid]; }, commitMount: function (instance, type, newProps, internalInstanceHandle) { + instanceMap.set(instance.uid, instance); const { commitMount } = getComponentByTagName(type); return commitMount(instance, newProps, internalInstanceHandle); }, From 1b094ba40c53488c581730ed828a1544f8e4da08 Mon Sep 17 00:00:00 2001 From: EmixamPP Date: Tue, 2 Jul 2024 11:30:58 +0200 Subject: [PATCH 2/5] fix: free styles on component deletion --- src/render/native/core/basic/comp.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/render/native/core/basic/comp.cpp b/src/render/native/core/basic/comp.cpp index 7d26e20..4098ba1 100644 --- a/src/render/native/core/basic/comp.cpp +++ b/src/render/native/core/basic/comp.cpp @@ -86,7 +86,7 @@ void BasicComponent::setTransition (JSContext* ctx, JSValue obj, lv_style_t* sty lv_style_prop_t* old_transProps = this->trans_props_map[type]; this->trans_props_map[type] = (lv_style_prop_t*)malloc((len + 1) * sizeof(lv_style_prop_t)); - + JSValue props = JS_GetPropertyUint32(ctx, obj, 1); int32_t prop_key; for(int i=0; i < len; i++) { @@ -255,6 +255,11 @@ BasicComponent::~BasicComponent () { if (ptr2) { free((lv_coord_t*)(ptr2)); } + + for(auto &style : style_map) { + lv_style_reset(style.second); + } + // do not del here, remove child will do the action // lv_obj_del(this->instance); }; From 6be145f7ee2dc4741ae3fe20c4564b7c98d15113 Mon Sep 17 00:00:00 2001 From: EmixamPP Date: Wed, 31 Jul 2024 09:55:55 +0200 Subject: [PATCH 3/5] fix: remove lvgl event callback on component deletion This cause a segfault --- src/render/native/components/component.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/render/native/components/component.hpp b/src/render/native/components/component.hpp index 2fb8633..61731f5 100644 --- a/src/render/native/components/component.hpp +++ b/src/render/native/components/component.hpp @@ -284,7 +284,10 @@ void NativeComponentMaskInit (JSContext* ctx, JSValue ns); #define WRAPPED_JS_CLOSE_COMPONENT(COMPONENT,COMPONENT_NAME) \ static JSValue NativeCompCloseComponent(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { \ COMP_REF* s = (COMP_REF*)JS_GetOpaque(this_val, COMPONENT##ClassID); \ - lv_obj_del_async(((BasicComponent*)(s->comp))->instance); \ + lv_obj_t* instance = ((BasicComponent*)(s->comp))->instance; \ + ((BasicComponent*)(s->comp))->instance = nullptr; \ + lv_obj_remove_event_cb(instance, &BasicComponent::EventCallback); \ + lv_obj_del_async(instance); \ return JS_UNDEFINED; \ } \ \ From 44e4cdefe38a4d281bb8324d8acef037a6da1b5a Mon Sep 17 00:00:00 2001 From: EmixamPP Date: Tue, 27 Aug 2024 09:09:09 +0200 Subject: [PATCH 4/5] fix: getInstance returns nullptr --- src/render/react/core/reconciler/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/react/core/reconciler/index.js b/src/render/react/core/reconciler/index.js index 5cf4786..d371c25 100644 --- a/src/render/react/core/reconciler/index.js +++ b/src/render/react/core/reconciler/index.js @@ -11,7 +11,7 @@ export const getUid = () => { const instanceMap = new Map(); export const getInstance = (uid) => { - return instanceMap[uid]; + return instanceMap.get(uid); }; const HostConfig = { From 83a959f854f6e9203b324f8057acc73806e95d65 Mon Sep 17 00:00:00 2001 From: EmixamPP Date: Tue, 1 Oct 2024 10:32:50 +0200 Subject: [PATCH 5/5] fix: random crash after view switch --- src/render/native/components/component.hpp | 5 +---- src/render/native/core/basic/comp.cpp | 8 +++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/render/native/components/component.hpp b/src/render/native/components/component.hpp index 61731f5..4507e25 100644 --- a/src/render/native/components/component.hpp +++ b/src/render/native/components/component.hpp @@ -284,10 +284,7 @@ void NativeComponentMaskInit (JSContext* ctx, JSValue ns); #define WRAPPED_JS_CLOSE_COMPONENT(COMPONENT,COMPONENT_NAME) \ static JSValue NativeCompCloseComponent(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { \ COMP_REF* s = (COMP_REF*)JS_GetOpaque(this_val, COMPONENT##ClassID); \ - lv_obj_t* instance = ((BasicComponent*)(s->comp))->instance; \ - ((BasicComponent*)(s->comp))->instance = nullptr; \ - lv_obj_remove_event_cb(instance, &BasicComponent::EventCallback); \ - lv_obj_del_async(instance); \ + delete (BasicComponent*)(s->comp); \ return JS_UNDEFINED; \ } \ \ diff --git a/src/render/native/core/basic/comp.cpp b/src/render/native/core/basic/comp.cpp index 4098ba1..d6dd92a 100644 --- a/src/render/native/core/basic/comp.cpp +++ b/src/render/native/core/basic/comp.cpp @@ -45,9 +45,7 @@ void BasicComponent::insertChildBefore(void *child) { } }; -void BasicComponent::removeChild(void* child) { - lv_obj_del_async((static_cast(child))->instance); -}; +void BasicComponent::removeChild(void* child) {}; void BasicComponent::appendChild (void* child) { static_cast(child)->parent_instance = this->instance; @@ -260,8 +258,8 @@ BasicComponent::~BasicComponent () { lv_style_reset(style.second); } - // do not del here, remove child will do the action - // lv_obj_del(this->instance); + lv_obj_remove_event_cb(instance, &BasicComponent::EventCallback); + lv_obj_del(this->instance); }; void BasicComponent::setAlign (int32_t align_type, int32_t x, int32_t y) {