From e1d3cf93ce0fae211f6d5a88a89ec9b127df9d33 Mon Sep 17 00:00:00 2001 From: Guilherme Simoes Date: Thu, 8 Oct 2026 17:26:30 +0100 Subject: [PATCH 1/2] Add new test --- tests/textures/test.textures.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/textures/test.textures.js b/tests/textures/test.textures.js index 3d1da282..32caf91c 100644 --- a/tests/textures/test.textures.js +++ b/tests/textures/test.textures.js @@ -487,6 +487,7 @@ describe('Textures', function() { chai.assert(texture.isLoaded(), "Texture must be loaded"); }); + it('should recover load [with throttling]', () => { const element = app.stage.createElement({ Item: {x: 550, texture: {type: TestTexture, async: true}} @@ -595,6 +596,25 @@ describe('Textures', function() { chai.assert(!stage.textureManager.getReusableTextureSource("test1"), "lookup id should be removed"); }); + + it('should release old source when element becomes inactive after src swap', () => { + const element = app.stage.createElement({ + Item: {texture: {type: TestTexture, lookupId: "old"}} + }); + app.children = [element]; + stage.drawFrame(); + + const item = app.tag("Item"); + const oldTextureSource = item.texture.source; + + item.texture = {type: TestTexture, lookupId: "new"}; + item.visible = false; + stage.drawFrame(); + stage.gc(); + + chai.assert(!oldTextureSource.isUsed(), "Old texture source should no longer be in use"); + chai.assert(!stage.textureManager._uploadedTextureSources.includes(oldTextureSource), "Old texture source should be cleaned up by gc"); + }); }); describe('previously removed texture source', () => { From 7fd7485aa01da077b1b579d9a5dfb19709bcbbab Mon Sep 17 00:00:00 2001 From: Guilherme Simoes Date: Thu, 8 Oct 2026 17:55:00 +0100 Subject: [PATCH 2/2] Fix memory leak when element becomes inactive after src swap --- src/tree/Element.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tree/Element.mjs b/src/tree/Element.mjs index 57d9f612..49afd321 100644 --- a/src/tree/Element.mjs +++ b/src/tree/Element.mjs @@ -405,6 +405,10 @@ export default class Element { _unsetActiveFlag() { if (this.__texture) { this.__texture.decActiveCount(); + + if (this.__displayedTexture && this.__displayedTexture !== this.__texture) { + this.__displayedTexture.decActiveCount(); + } } this.__active = false;