From 4cad96ff73c2f80fd924398c8bf829c9cdaa81f4 Mon Sep 17 00:00:00 2001 From: Anton Lavrevov Date: Mon, 18 Aug 2025 23:47:44 +0900 Subject: [PATCH] Avoid crash when node inside transformer was destroyed. close #1957 --- src/shapes/Transformer.ts | 16 ++++++++++++-- test/unit/Transformer-test.ts | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index e10c575c..65082e73 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -788,9 +788,11 @@ export class Transformer extends Group { Math.pow(comparePoint.y - anchorNode.y(), 2) ); - const reverseX = this.findOne('.top-left')!.x() > comparePoint.x ? -1 : 1; + const reverseX = + this.findOne('.top-left')!.x() > comparePoint.x ? -1 : 1; - const reverseY = this.findOne('.top-left')!.y() > comparePoint.y ? -1 : 1; + const reverseY = + this.findOne('.top-left')!.y() > comparePoint.y ? -1 : 1; x = newHypotenuse * this.cos * reverseX; y = newHypotenuse * this.sin * reverseY; @@ -1107,6 +1109,16 @@ export class Transformer extends Group { const delta = newTr.multiply(oldTr.invert()); this._nodes.forEach((node) => { + // check to close this issue: https://github.com/konvajs/konva/issues/1957 + // a node can be destroyed during the transformation + // probably a developer must remove it from transformer + if (!node.getStage()) { + // do we need a helping message? + // Util.error( + // 'Node is not attached to the stage. This is not allowed. Please attach the node to the stage before transforming. If node was destroyed, make sure to remove it from transformer.' + // ); + return; + } // for each node we have the same [delta transform] // the equations is // [delta transform] * [parent transform] * [old local transform] = [parent transform] * [new local transform] diff --git a/test/unit/Transformer-test.ts b/test/unit/Transformer-test.ts index 14212a02..f410b635 100644 --- a/test/unit/Transformer-test.ts +++ b/test/unit/Transformer-test.ts @@ -5141,4 +5141,43 @@ describe('Transformer', function () { 'Event listeners should be cleaned up properly' ); }); + + it.only('should handle transformation when node is not on stage (case for node destroy)', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + // Create a rect but don't add it to stage yet + var rect = new Konva.Rect({ + x: 50, + y: 50, + width: 100, + height: 100, + fill: 'yellow', + }); + + var tr = new Konva.Transformer({ + nodes: [rect], + }); + layer.add(tr); + + // Should not throw error when drawing with node not on stage + layer.draw(); + + // Transformer should have zero size when node is not on stage + + // Try to move an anchor to trigger transformation - should throw error + simulateMouseDown(tr, { + x: 50, + y: 50, + }); + simulateMouseMove(tr, { + x: 60, + y: 60, + }); + simulateMouseUp(tr, { + x: 60, + y: 60, + }); + }); });